-
Notifications
You must be signed in to change notification settings - Fork 1
/
Indenting.py
71 lines (59 loc) · 2.21 KB
/
Indenting.py
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
from sys import stdout
from contextlib import AbstractContextManager
class Indenting(AbstractContextManager):
'''A wrapper for a file object that adds automatic indentation of lines.
The wrapper is a context manager: every entrance into a new context
increases the indent level by 1, and every exit decreases it by 1.
The Indenting object has a .wrote_any member, which is True iff at least
one character has been written to the object since it was created.
It's OK to reset it to False from the outside.'''
def __init__(self, file, prefix = ' ' * 4):
self.file = file
self.at_start_of_line = True
self.prefix = prefix
self.level = 0
self.wrote_any = False
def __getattr__(self, name):
if name == 'write':
return self.write_with_indent
else:
return getattr(self.file, name)
# __getattr__ doesn't intercept __iter__
def __iter__(self, *args, **kwargs):
return self.file.__iter__(*args, **kwargs)
def write_with_indent(self, s):
if not s:
return 0
self.wrote_any = True
if s == '\n':
self.at_start_of_line = True
return self.file.write(s)
num_written = 0
for line in s.splitlines(keepends=True):
if self.at_start_of_line:
num_written += self.file.write(self.prefix * self.level)
num_written += self.file.write(line)
self.at_start_of_line = True
self.at_start_of_line = s[-1] == '\n'
return num_written
def __enter__(self):
self.level += 1
return self
def __exit__(self, *args, **kwargs):
self.level -= 1
return None
def indent(f):
'''A function to make 'with' statements more readable: with indent(f): ...
f must be an Indenting object.'''
if not isinstance(f, Indenting):
raise ValueError('Object must be an instance of Indenting.')
return f
def run():
f = Indenting(stdout)
print('Blah', file=f)
with indent(f):
print('Indented\nGah', file=f)
with indent(f):
print('Indented twice', file=f)
print('Back to once', file=f)
print('Back to nothing', file=f)