blob: e2394de8c291952cf960132319d6b59831ea1a18 [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
Brett Cannon1448ecf2013-10-04 11:38:59 -040022import warnings
Brett Cannon5ad5a7d2015-10-16 12:09:33 -070023warnings.warn('the formatter module is deprecated', DeprecationWarning,
24 stacklevel=2)
Guido van Rossuma0eab1d1995-08-07 20:07:36 +000025
26
27AS_IS = None
28
Guido van Rossuma0eab1d1995-08-07 20:07:36 +000029
Guido van Rossum909507d1995-10-06 15:31:30 +000030class NullFormatter:
Raymond Hettingeraef22fb2002-05-29 16:18:42 +000031 """A formatter which does nothing.
32
33 If the writer parameter is omitted, a NullWriter instance is created.
34 No methods of the writer are called by NullFormatter instances.
35
36 Implementations should inherit from this class if implementing a writer
37 interface but don't need to inherit any implementation.
38
39 """
Guido van Rossum909507d1995-10-06 15:31:30 +000040
Guido van Rossumccd8b191996-10-07 21:29:49 +000041 def __init__(self, writer=None):
Raymond Hettinger094662a2002-06-01 01:29:16 +000042 if writer is None:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000043 writer = NullWriter()
44 self.writer = writer
Guido van Rossum909507d1995-10-06 15:31:30 +000045 def end_paragraph(self, blankline): pass
46 def add_line_break(self): pass
Fred Drakeca8cdc61996-10-08 21:57:47 +000047 def add_hor_rule(self, *args, **kw): pass
48 def add_label_data(self, format, counter, blankline=None): pass
Guido van Rossum909507d1995-10-06 15:31:30 +000049 def add_flowing_data(self, data): pass
50 def add_literal_data(self, data): pass
51 def flush_softspace(self): pass
Guido van Rossum9787bdaf1996-05-28 23:50:49 +000052 def push_alignment(self, align): pass
53 def pop_alignment(self): pass
Guido van Rossum909507d1995-10-06 15:31:30 +000054 def push_font(self, x): pass
55 def pop_font(self): pass
56 def push_margin(self, margin): pass
57 def pop_margin(self): pass
58 def set_spacing(self, spacing): pass
Guido van Rossum9787bdaf1996-05-28 23:50:49 +000059 def push_style(self, *styles): pass
60 def pop_style(self, n=1): pass
61 def assert_line_data(self, flag=1): pass
Guido van Rossum909507d1995-10-06 15:31:30 +000062
63
Guido van Rossuma0eab1d1995-08-07 20:07:36 +000064class AbstractFormatter:
Raymond Hettingeraef22fb2002-05-29 16:18:42 +000065 """The standard formatter.
66
67 This implementation has demonstrated wide applicability to many writers,
68 and may be used directly in most circumstances. It has been used to
69 implement a full-featured World Wide Web browser.
70
71 """
Guido van Rossuma0eab1d1995-08-07 20:07:36 +000072
Guido van Rossum8e449911996-08-26 16:19:23 +000073 # Space handling policy: blank spaces at the boundary between elements
74 # are handled by the outermost context. "Literal" data is not checked
75 # to determine context, so spaces in literal data are handled directly
76 # in all circumstances.
77
Guido van Rossuma0eab1d1995-08-07 20:07:36 +000078 def __init__(self, writer):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000079 self.writer = writer # Output device
80 self.align = None # Current alignment
81 self.align_stack = [] # Alignment stack
82 self.font_stack = [] # Font state
83 self.margin_stack = [] # Margin state
84 self.spacing = None # Vertical spacing state
85 self.style_stack = [] # Other state, e.g. color
86 self.nospace = 1 # Should leading space be suppressed
87 self.softspace = 0 # Should a space be inserted
88 self.para_end = 1 # Just ended a paragraph
89 self.parskip = 0 # Skipped space between paragraphs?
90 self.hard_break = 1 # Have a hard break
91 self.have_label = 0
Guido van Rossuma0eab1d1995-08-07 20:07:36 +000092
93 def end_paragraph(self, blankline):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000094 if not self.hard_break:
95 self.writer.send_line_break()
96 self.have_label = 0
97 if self.parskip < blankline and not self.have_label:
98 self.writer.send_paragraph(blankline - self.parskip)
99 self.parskip = blankline
100 self.have_label = 0
101 self.hard_break = self.nospace = self.para_end = 1
102 self.softspace = 0
Guido van Rossuma0eab1d1995-08-07 20:07:36 +0000103
104 def add_line_break(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000105 if not (self.hard_break or self.para_end):
106 self.writer.send_line_break()
107 self.have_label = self.parskip = 0
108 self.hard_break = self.nospace = 1
109 self.softspace = 0
Guido van Rossuma0eab1d1995-08-07 20:07:36 +0000110
Guido van Rossum9787bdaf1996-05-28 23:50:49 +0000111 def add_hor_rule(self, *args, **kw):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000112 if not self.hard_break:
113 self.writer.send_line_break()
Guido van Rossum68468eb2003-02-27 20:14:51 +0000114 self.writer.send_hor_rule(*args, **kw)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000115 self.hard_break = self.nospace = 1
116 self.have_label = self.para_end = self.softspace = self.parskip = 0
Guido van Rossuma0eab1d1995-08-07 20:07:36 +0000117
Guido van Rossum9787bdaf1996-05-28 23:50:49 +0000118 def add_label_data(self, format, counter, blankline = None):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000119 if self.have_label or not self.hard_break:
120 self.writer.send_line_break()
121 if not self.para_end:
122 self.writer.send_paragraph((blankline and 1) or 0)
Walter Dörwald65230a22002-06-03 15:58:32 +0000123 if isinstance(format, str):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000124 self.writer.send_label_data(self.format_counter(format, counter))
125 else:
126 self.writer.send_label_data(format)
127 self.nospace = self.have_label = self.hard_break = self.para_end = 1
128 self.softspace = self.parskip = 0
Guido van Rossuma0eab1d1995-08-07 20:07:36 +0000129
130 def format_counter(self, format, counter):
Guido van Rossuma0eab1d1995-08-07 20:07:36 +0000131 label = ''
132 for c in format:
Fred Drake6f6a14f2001-05-11 19:25:08 +0000133 if c == '1':
134 label = label + ('%d' % counter)
135 elif c in 'aA':
136 if counter > 0:
137 label = label + self.format_letter(c, counter)
138 elif c in 'iI':
139 if counter > 0:
140 label = label + self.format_roman(c, counter)
141 else:
Guido van Rossum9787bdaf1996-05-28 23:50:49 +0000142 label = label + c
Guido van Rossuma0eab1d1995-08-07 20:07:36 +0000143 return label
144
145 def format_letter(self, case, counter):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000146 label = ''
147 while counter > 0:
148 counter, x = divmod(counter-1, 26)
Fred Drake6f6a14f2001-05-11 19:25:08 +0000149 # This makes a strong assumption that lowercase letters
150 # and uppercase letters form two contiguous blocks, with
151 # letters in order!
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000152 s = chr(ord(case) + x)
153 label = s + label
154 return label
Guido van Rossuma0eab1d1995-08-07 20:07:36 +0000155
156 def format_roman(self, case, counter):
157 ones = ['i', 'x', 'c', 'm']
158 fives = ['v', 'l', 'd']
Guido van Rossum9787bdaf1996-05-28 23:50:49 +0000159 label, index = '', 0
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000160 # This will die of IndexError when counter is too big
Guido van Rossuma0eab1d1995-08-07 20:07:36 +0000161 while counter > 0:
162 counter, x = divmod(counter, 10)
163 if x == 9:
Guido van Rossum9787bdaf1996-05-28 23:50:49 +0000164 label = ones[index] + ones[index+1] + label
Guido van Rossuma0eab1d1995-08-07 20:07:36 +0000165 elif x == 4:
Guido van Rossum9787bdaf1996-05-28 23:50:49 +0000166 label = ones[index] + fives[index] + label
Guido van Rossuma0eab1d1995-08-07 20:07:36 +0000167 else:
168 if x >= 5:
169 s = fives[index]
170 x = x-5
171 else:
172 s = ''
173 s = s + ones[index]*x
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000174 label = s + label
Guido van Rossuma0eab1d1995-08-07 20:07:36 +0000175 index = index + 1
Guido van Rossum9787bdaf1996-05-28 23:50:49 +0000176 if case == 'I':
Eric S. Raymondb08b2d32001-02-09 11:10:16 +0000177 return label.upper()
Guido van Rossuma0eab1d1995-08-07 20:07:36 +0000178 return label
179
Walter Dörwald65230a22002-06-03 15:58:32 +0000180 def add_flowing_data(self, data):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000181 if not data: return
Walter Dörwald65230a22002-06-03 15:58:32 +0000182 prespace = data[:1].isspace()
183 postspace = data[-1:].isspace()
184 data = " ".join(data.split())
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000185 if self.nospace and not data:
186 return
187 elif prespace or self.softspace:
188 if not data:
189 if not self.nospace:
190 self.softspace = 1
191 self.parskip = 0
192 return
193 if not self.nospace:
194 data = ' ' + data
195 self.hard_break = self.nospace = self.para_end = \
196 self.parskip = self.have_label = 0
197 self.softspace = postspace
198 self.writer.send_flowing_data(data)
Guido van Rossuma0eab1d1995-08-07 20:07:36 +0000199
200 def add_literal_data(self, data):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000201 if not data: return
202 if self.softspace:
203 self.writer.send_flowing_data(" ")
204 self.hard_break = data[-1:] == '\n'
205 self.nospace = self.para_end = self.softspace = \
206 self.parskip = self.have_label = 0
207 self.writer.send_literal_data(data)
Guido van Rossuma0eab1d1995-08-07 20:07:36 +0000208
Guido van Rossumc7ae9201995-09-30 16:49:58 +0000209 def flush_softspace(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000210 if self.softspace:
211 self.hard_break = self.para_end = self.parskip = \
212 self.have_label = self.softspace = 0
213 self.nospace = 1
214 self.writer.send_flowing_data(' ')
Guido van Rossumc7ae9201995-09-30 16:49:58 +0000215
Guido van Rossum9787bdaf1996-05-28 23:50:49 +0000216 def push_alignment(self, align):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000217 if align and align != self.align:
218 self.writer.new_alignment(align)
219 self.align = align
220 self.align_stack.append(align)
221 else:
222 self.align_stack.append(self.align)
Guido van Rossum9787bdaf1996-05-28 23:50:49 +0000223
224 def pop_alignment(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000225 if self.align_stack:
226 del self.align_stack[-1]
227 if self.align_stack:
228 self.align = align = self.align_stack[-1]
229 self.writer.new_alignment(align)
230 else:
231 self.align = None
232 self.writer.new_alignment(None)
Guido van Rossum9787bdaf1996-05-28 23:50:49 +0000233
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000234 def push_font(self, font):
235 size, i, b, tt = font
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000236 if self.softspace:
237 self.hard_break = self.para_end = self.softspace = 0
238 self.nospace = 1
239 self.writer.send_flowing_data(' ')
240 if self.font_stack:
241 csize, ci, cb, ctt = self.font_stack[-1]
242 if size is AS_IS: size = csize
243 if i is AS_IS: i = ci
244 if b is AS_IS: b = cb
245 if tt is AS_IS: tt = ctt
246 font = (size, i, b, tt)
247 self.font_stack.append(font)
248 self.writer.new_font(font)
Guido van Rossuma0eab1d1995-08-07 20:07:36 +0000249
250 def pop_font(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000251 if self.font_stack:
252 del self.font_stack[-1]
253 if self.font_stack:
254 font = self.font_stack[-1]
255 else:
256 font = None
257 self.writer.new_font(font)
Guido van Rossuma0eab1d1995-08-07 20:07:36 +0000258
259 def push_margin(self, margin):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000260 self.margin_stack.append(margin)
Georg Brandl7cd67cc2008-09-09 19:31:25 +0000261 fstack = [m for m in self.margin_stack if m]
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000262 if not margin and fstack:
263 margin = fstack[-1]
264 self.writer.new_margin(margin, len(fstack))
Guido van Rossuma0eab1d1995-08-07 20:07:36 +0000265
266 def pop_margin(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000267 if self.margin_stack:
268 del self.margin_stack[-1]
Georg Brandl7cd67cc2008-09-09 19:31:25 +0000269 fstack = [m for m in self.margin_stack if m]
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000270 if fstack:
271 margin = fstack[-1]
272 else:
273 margin = None
274 self.writer.new_margin(margin, len(fstack))
Guido van Rossuma0eab1d1995-08-07 20:07:36 +0000275
276 def set_spacing(self, spacing):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000277 self.spacing = spacing
278 self.writer.new_spacing(spacing)
Guido van Rossuma0eab1d1995-08-07 20:07:36 +0000279
Guido van Rossum9787bdaf1996-05-28 23:50:49 +0000280 def push_style(self, *styles):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000281 if self.softspace:
282 self.hard_break = self.para_end = self.softspace = 0
283 self.nospace = 1
284 self.writer.send_flowing_data(' ')
285 for style in styles:
286 self.style_stack.append(style)
287 self.writer.new_styles(tuple(self.style_stack))
Guido van Rossuma0eab1d1995-08-07 20:07:36 +0000288
Guido van Rossum9787bdaf1996-05-28 23:50:49 +0000289 def pop_style(self, n=1):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000290 del self.style_stack[-n:]
291 self.writer.new_styles(tuple(self.style_stack))
Guido van Rossuma0eab1d1995-08-07 20:07:36 +0000292
Guido van Rossum9787bdaf1996-05-28 23:50:49 +0000293 def assert_line_data(self, flag=1):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000294 self.nospace = self.hard_break = not flag
295 self.para_end = self.parskip = self.have_label = 0
Guido van Rossum9787bdaf1996-05-28 23:50:49 +0000296
297
298class NullWriter:
Raymond Hettingeraef22fb2002-05-29 16:18:42 +0000299 """Minimal writer interface to use in testing & inheritance.
300
301 A writer which only provides the interface definition; no actions are
302 taken on any methods. This should be the base class for all writers
303 which do not need to inherit any implementation methods.
304
305 """
Guido van Rossum3672aa21996-05-29 00:02:30 +0000306 def __init__(self): pass
Fred Drake28231681996-12-31 20:50:51 +0000307 def flush(self): pass
Guido van Rossum9787bdaf1996-05-28 23:50:49 +0000308 def new_alignment(self, align): pass
309 def new_font(self, font): pass
310 def new_margin(self, margin, level): pass
311 def new_spacing(self, spacing): pass
312 def new_styles(self, styles): pass
313 def send_paragraph(self, blankline): pass
314 def send_line_break(self): pass
315 def send_hor_rule(self, *args, **kw): pass
316 def send_label_data(self, data): pass
317 def send_flowing_data(self, data): pass
318 def send_literal_data(self, data): pass
319
Guido van Rossuma0eab1d1995-08-07 20:07:36 +0000320
Guido van Rossum3672aa21996-05-29 00:02:30 +0000321class AbstractWriter(NullWriter):
Raymond Hettingeraef22fb2002-05-29 16:18:42 +0000322 """A writer which can be used in debugging formatters, but not much else.
323
324 Each method simply announces itself by printing its name and
325 arguments on standard output.
326
327 """
Guido van Rossuma0eab1d1995-08-07 20:07:36 +0000328
Guido van Rossum9787bdaf1996-05-28 23:50:49 +0000329 def new_alignment(self, align):
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000330 print("new_alignment(%r)" % (align,))
Guido van Rossum9787bdaf1996-05-28 23:50:49 +0000331
Guido van Rossuma0eab1d1995-08-07 20:07:36 +0000332 def new_font(self, font):
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000333 print("new_font(%r)" % (font,))
Guido van Rossuma0eab1d1995-08-07 20:07:36 +0000334
335 def new_margin(self, margin, level):
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000336 print("new_margin(%r, %d)" % (margin, level))
Guido van Rossuma0eab1d1995-08-07 20:07:36 +0000337
338 def new_spacing(self, spacing):
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000339 print("new_spacing(%r)" % (spacing,))
Guido van Rossuma0eab1d1995-08-07 20:07:36 +0000340
341 def new_styles(self, styles):
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000342 print("new_styles(%r)" % (styles,))
Guido van Rossuma0eab1d1995-08-07 20:07:36 +0000343
344 def send_paragraph(self, blankline):
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000345 print("send_paragraph(%r)" % (blankline,))
Guido van Rossuma0eab1d1995-08-07 20:07:36 +0000346
347 def send_line_break(self):
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000348 print("send_line_break()")
Guido van Rossuma0eab1d1995-08-07 20:07:36 +0000349
Guido van Rossum9787bdaf1996-05-28 23:50:49 +0000350 def send_hor_rule(self, *args, **kw):
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000351 print("send_hor_rule()")
Guido van Rossuma0eab1d1995-08-07 20:07:36 +0000352
353 def send_label_data(self, data):
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000354 print("send_label_data(%r)" % (data,))
Guido van Rossuma0eab1d1995-08-07 20:07:36 +0000355
356 def send_flowing_data(self, data):
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000357 print("send_flowing_data(%r)" % (data,))
Guido van Rossuma0eab1d1995-08-07 20:07:36 +0000358
359 def send_literal_data(self, data):
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000360 print("send_literal_data(%r)" % (data,))
Guido van Rossuma0eab1d1995-08-07 20:07:36 +0000361
362
Guido van Rossum3672aa21996-05-29 00:02:30 +0000363class DumbWriter(NullWriter):
Raymond Hettingeraef22fb2002-05-29 16:18:42 +0000364 """Simple writer class which writes output on the file object passed in
365 as the file parameter or, if file is omitted, on standard output. The
366 output is simply word-wrapped to the number of columns specified by
367 the maxcol parameter. This class is suitable for reflowing a sequence
368 of paragraphs.
369
370 """
Guido van Rossuma0eab1d1995-08-07 20:07:36 +0000371
372 def __init__(self, file=None, maxcol=72):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000373 self.file = file or sys.stdout
374 self.maxcol = maxcol
375 NullWriter.__init__(self)
376 self.reset()
Guido van Rossuma0eab1d1995-08-07 20:07:36 +0000377
378 def reset(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000379 self.col = 0
380 self.atbreak = 0
Guido van Rossuma0eab1d1995-08-07 20:07:36 +0000381
382 def send_paragraph(self, blankline):
Fred Drakef4bb6561999-01-12 18:13:27 +0000383 self.file.write('\n'*blankline)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000384 self.col = 0
385 self.atbreak = 0
Guido van Rossuma0eab1d1995-08-07 20:07:36 +0000386
387 def send_line_break(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000388 self.file.write('\n')
389 self.col = 0
390 self.atbreak = 0
Guido van Rossuma0eab1d1995-08-07 20:07:36 +0000391
Guido van Rossum9787bdaf1996-05-28 23:50:49 +0000392 def send_hor_rule(self, *args, **kw):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000393 self.file.write('\n')
394 self.file.write('-'*self.maxcol)
395 self.file.write('\n')
396 self.col = 0
397 self.atbreak = 0
Guido van Rossuma0eab1d1995-08-07 20:07:36 +0000398
399 def send_literal_data(self, data):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000400 self.file.write(data)
Eric S. Raymondb08b2d32001-02-09 11:10:16 +0000401 i = data.rfind('\n')
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000402 if i >= 0:
403 self.col = 0
404 data = data[i+1:]
Eric S. Raymondb08b2d32001-02-09 11:10:16 +0000405 data = data.expandtabs()
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000406 self.col = self.col + len(data)
407 self.atbreak = 0
Guido van Rossuma0eab1d1995-08-07 20:07:36 +0000408
409 def send_flowing_data(self, data):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000410 if not data: return
Walter Dörwald65230a22002-06-03 15:58:32 +0000411 atbreak = self.atbreak or data[0].isspace()
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000412 col = self.col
413 maxcol = self.maxcol
414 write = self.file.write
Eric S. Raymondb08b2d32001-02-09 11:10:16 +0000415 for word in data.split():
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000416 if atbreak:
417 if col + len(word) >= maxcol:
418 write('\n')
419 col = 0
420 else:
421 write(' ')
422 col = col + 1
423 write(word)
424 col = col + len(word)
425 atbreak = 1
426 self.col = col
Walter Dörwald65230a22002-06-03 15:58:32 +0000427 self.atbreak = data[-1].isspace()
Guido van Rossuma0eab1d1995-08-07 20:07:36 +0000428
429
430def test(file = None):
431 w = DumbWriter()
432 f = AbstractFormatter(w)
Raymond Hettinger094662a2002-06-01 01:29:16 +0000433 if file is not None:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000434 fp = open(file)
Guido van Rossuma0eab1d1995-08-07 20:07:36 +0000435 elif sys.argv[1:]:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000436 fp = open(sys.argv[1])
Guido van Rossuma0eab1d1995-08-07 20:07:36 +0000437 else:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000438 fp = sys.stdin
Berker Peksagd91082c2015-01-05 09:19:40 +0200439 try:
440 for line in fp:
441 if line == '\n':
442 f.end_paragraph(1)
443 else:
444 f.add_flowing_data(line)
445 finally:
446 if fp is not sys.stdin:
447 fp.close()
Guido van Rossuma0eab1d1995-08-07 20:07:36 +0000448 f.end_paragraph(0)
449
450
451if __name__ == '__main__':
452 test()