|
73 | 73 | # - realign comments |
74 | 74 | # - optionally do much more thorough reformatting, a la C indent |
75 | 75 |
|
| 76 | +# Defaults |
| 77 | +STEPSIZE = 8 |
| 78 | +TABSIZE = 8 |
| 79 | + |
76 | 80 | import os |
77 | 81 | import regex |
78 | 82 | import string |
|
90 | 94 | class PythonIndenter: |
91 | 95 |
|
92 | 96 | def __init__(self, fpi = sys.stdin, fpo = sys.stdout, |
93 | | - indentsize = 8, tabsize = 8): |
| 97 | + indentsize = STEPSIZE, tabsize = TABSIZE): |
94 | 98 | self.fpi = fpi |
95 | 99 | self.fpo = fpo |
96 | 100 | self.indentsize = indentsize |
@@ -273,40 +277,162 @@ def complete(self): |
273 | 277 |
|
274 | 278 | # end class PythonIndenter |
275 | 279 |
|
| 280 | +# Simplified user interface |
| 281 | +# - xxx_filter(input, output): read and write file objects |
| 282 | +# - xxx_string(s): take and return string object |
| 283 | +# - xxx_file(filename): process file in place, return true iff changed |
| 284 | + |
| 285 | +def complete_filter(input= sys.stdin, output = sys.stdout, |
| 286 | + stepsize = STEPSIZE, tabsize = TABSIZE): |
| 287 | + pi = PythonIndenter(input, output, stepsize, tabsize) |
| 288 | + pi.complete() |
| 289 | +# end def complete_filter |
| 290 | + |
| 291 | +def reformat_filter(input = sys.stdin, output = sys.stdout, |
| 292 | + stepsize = STEPSIZE, tabsize = TABSIZE): |
| 293 | + pi = PythonIndenter(input, output, stepsize, tabsize) |
| 294 | + pi.reformat() |
| 295 | +# end def reformat |
| 296 | + |
| 297 | +class StringReader: |
| 298 | + def __init__(self, buf): |
| 299 | + self.buf = buf |
| 300 | + self.pos = 0 |
| 301 | + self.len = len(self.buf) |
| 302 | + # end def __init__ |
| 303 | + def read(self, n = 0): |
| 304 | + if n <= 0: |
| 305 | + n = self.len - self.pos |
| 306 | + else: |
| 307 | + n = min(n, self.len - self.pos) |
| 308 | + # end if |
| 309 | + r = self.buf[self.pos : self.pos + n] |
| 310 | + self.pos = self.pos + n |
| 311 | + return r |
| 312 | + # end def read |
| 313 | + def readline(self): |
| 314 | + i = string.find(self.buf, '\n', self.pos) |
| 315 | + return self.read(i + 1 - self.pos) |
| 316 | + # end def readline |
| 317 | + def readlines(self): |
| 318 | + lines = [] |
| 319 | + line = self.readline() |
| 320 | + while line: |
| 321 | + lines.append(line) |
| 322 | + line = self.readline() |
| 323 | + # end while |
| 324 | + return lines |
| 325 | + # end def readlines |
| 326 | + # seek/tell etc. are left as an exercise for the reader |
| 327 | +# end class StringReader |
| 328 | + |
| 329 | +class StringWriter: |
| 330 | + def __init__(self): |
| 331 | + self.buf = '' |
| 332 | + # end def __init__ |
| 333 | + def write(self, s): |
| 334 | + self.buf = self.buf + s |
| 335 | + # end def write |
| 336 | + def getvalue(self): |
| 337 | + return self.buf |
| 338 | + # end def getvalue |
| 339 | +# end class StringWriter |
| 340 | + |
| 341 | +def complete_string(source, stepsize = STEPSIZE, tabsize = TABSIZE): |
| 342 | + input = StringReader(source) |
| 343 | + output = StringWriter() |
| 344 | + pi = PythonIndenter(input, output, stepsize, tabsize) |
| 345 | + pi.complete() |
| 346 | + return output.getvalue() |
| 347 | +# end def complete_string |
| 348 | + |
| 349 | +def reformat_string(source, stepsize = STEPSIZE, tabsize = TABSIZE): |
| 350 | + input = StringReader(source) |
| 351 | + output = StringWriter() |
| 352 | + pi = PythonIndenter(input, output, stepsize, tabsize) |
| 353 | + pi.reformat() |
| 354 | + return output.getvalue() |
| 355 | +# end def reformat_string |
| 356 | + |
| 357 | +def complete_file(filename, stepsize = STEPSIZE, tabsize = TABSIZE): |
| 358 | + source = open(filename, 'r').read() |
| 359 | + result = complete_string(source, stepsize, tabsize) |
| 360 | + if source == result: return 0 |
| 361 | + # end if |
| 362 | + import os |
| 363 | + try: os.rename(filename, filename + '~') |
| 364 | + except os.error: pass |
| 365 | + # end try |
| 366 | + f = open(filename, 'w') |
| 367 | + f.write(result) |
| 368 | + f.close() |
| 369 | + return 1 |
| 370 | +# end def complete_file |
| 371 | + |
| 372 | +def reformat_file(filename, stepsize = STEPSIZE, tabsize = TABSIZE): |
| 373 | + source = open(filename, 'r').read() |
| 374 | + result = reformat_string(source, stepsize, tabsize) |
| 375 | + if source == result: return 0 |
| 376 | + # end if |
| 377 | + import os |
| 378 | + os.rename(filename, filename + '~') |
| 379 | + f = open(filename, 'w') |
| 380 | + f.write(result) |
| 381 | + f.close() |
| 382 | + return 1 |
| 383 | +# end def reformat_file |
| 384 | + |
| 385 | +# Test program when called as a script |
| 386 | + |
| 387 | +usage = """ |
| 388 | +usage: pindent (-c|-r) [-s stepsize] [-t tabsize] [file] ... |
| 389 | +-c : complete a correctly indented program (add #end directives) |
| 390 | +-r : reformat a completed program (use #end directives) |
| 391 | +-s stepsize: indentation step (default %(STEPSIZE)d) |
| 392 | +-t tabsize : the worth in spaces of a tab (default %(TABSIZE)d) |
| 393 | +[file] ... : files are changed in place, with backups in file~ |
| 394 | +If no files are specified or a single - is given, |
| 395 | +the program acts as a filter (reads stdin, writes stdout). |
| 396 | +""" % vars() |
| 397 | + |
276 | 398 | def test(): |
277 | 399 | import getopt |
278 | | - opts, args = getopt.getopt(sys.argv[1:], 'crs:t:') |
| 400 | + try: |
| 401 | + opts, args = getopt.getopt(sys.argv[1:], 'crs:t:') |
| 402 | + except getopt.error, msg: |
| 403 | + sys.stderr.write('Error: %s\n' % msg) |
| 404 | + sys.stderr.write(usage) |
| 405 | + sys.exit(2) |
| 406 | + # end try |
279 | 407 | action = None |
280 | | - stepsize = 8 |
281 | | - tabsize = 8 |
| 408 | + stepsize = STEPSIZE |
| 409 | + tabsize = TABSIZE |
282 | 410 | for o, a in opts: |
283 | 411 | if o == '-c': |
284 | | - action = PythonIndenter.complete |
| 412 | + action = 'complete' |
285 | 413 | elif o == '-r': |
286 | | - action = PythonIndenter.reformat |
| 414 | + action = 'reformat' |
287 | 415 | elif o == '-s': |
288 | 416 | stepsize = string.atoi(a) |
289 | 417 | elif o == '-t': |
290 | 418 | tabsize = string.atoi(a) |
291 | 419 | # end if |
292 | 420 | # end for |
293 | 421 | if not action: |
294 | | - print 'You must specify -c(omplete) or -r(eformat)' |
| 422 | + sys.stderr.write( |
| 423 | + 'You must specify -c(omplete) or -r(eformat)\n') |
| 424 | + sys.stderr.write(usage) |
295 | 425 | sys.exit(2) |
296 | 426 | # end if |
297 | | - if not args: args = ['-'] |
| 427 | + if not args or args == ['-']: |
| 428 | + action = eval(action + '_filter') |
| 429 | + action(sys.stdin, sys.stdout, stepsize, tabsize) |
| 430 | + else: |
| 431 | + action = eval(action + '_file') |
| 432 | + for file in args: |
| 433 | + action(file, stepsize, tabsize) |
| 434 | + # end for |
298 | 435 | # end if |
299 | | - for file in args: |
300 | | - if file == '-': |
301 | | - fp = sys.stdin |
302 | | - else: |
303 | | - fp = open(file, 'r') |
304 | | - # end if |
305 | | - pi = PythonIndenter(fp, sys.stdout, stepsize, tabsize) |
306 | | - action(pi) |
307 | | - if fp != sys.stdin: fp.close() |
308 | | - # end if |
309 | | - # end for |
310 | 436 | # end def test |
311 | 437 |
|
312 | 438 | if __name__ == '__main__': |
|
0 commit comments