diff --git a/implementations/python/preserves/text.py b/implementations/python/preserves/text.py index 8b1ddfe..d448126 100644 --- a/implementations/python/preserves/text.py +++ b/implementations/python/preserves/text.py @@ -312,8 +312,10 @@ def parse_with_annotations(bs, **kwargs): return Parser(input_buffer=bs, include_annotations=True, **kwargs).next() class Formatter(TextCodec): - def __init__(self, format_embedded=lambda x: x): + def __init__(self, format_embedded=lambda x: x, indent=None): super(Formatter, self).__init__() + self.indent_delta = 0 if indent is None else indent + self.indent_distance = 0 self.chunks = [] self._format_embedded = format_embedded @@ -325,6 +327,19 @@ class Formatter(TextCodec): def contents(self): return u''.join(self.chunks) + def is_indenting(self): + return self.indent_delta > 0 + + def write_indent(self): + if self.is_indenting(): + self.chunks.append('\n' + ' ' * self.indent_distance) + + def write_indent_space(self): + if self.is_indenting(): + self.write_indent() + else: + self.chunks.append(' ') + def write_stringlike_char(self, c): if c == '\\': self.chunks.append('\\\\') elif c == '\x08': self.chunks.append('\\b') @@ -334,15 +349,23 @@ class Formatter(TextCodec): elif c == '\x09': self.chunks.append('\\t') else: self.chunks.append(c) - def write_seq(self, opener, closer, vs): + def write_seq(self, opener, closer, vs, appender): + vs = list(vs) + itemcount = len(vs) self.chunks.append(opener) - first_item = True - for v in vs: - if first_item: - first_item = False - else: - self.chunks.append(' ') - self.append(v) + if itemcount == 0: + pass + elif itemcount == 1: + appender(vs[0]) + else: + self.indent_distance = self.indent_distance + self.indent_delta + self.write_indent() + appender(vs[0]) + for v in vs[1:]: + self.write_indent_space() + appender(v) + self.indent_distance = self.indent_distance - self.indent_delta + self.write_indent() self.chunks.append(closer) def append(self, v): @@ -366,25 +389,19 @@ class Formatter(TextCodec): else: self.write_stringlike_char(c) self.chunks.append('"') elif isinstance(v, list): - self.write_seq('[', ']', v) + self.write_seq('[', ']', v, self.append) elif isinstance(v, tuple): - self.write_seq('[', ']', v) + self.write_seq('[', ']', v, self.append) elif isinstance(v, set): - self.write_seq('#{', '}', v) + self.write_seq('#{', '}', v, self.append) elif isinstance(v, frozenset): - self.write_seq('#{', '}', v) + self.write_seq('#{', '}', v, self.append) elif isinstance(v, dict): - self.chunks.append('{') - need_comma = False - for (k, v) in v.items(): - if need_comma: - self.chunks.append(', ') - else: - need_comma = True - self.append(k) + def append_kv(kv): + self.append(kv[0]) self.chunks.append(': ') - self.append(v) - self.chunks.append('}') + self.append(kv[1]) + self.write_seq('{', '}', v.items(), append_kv) else: try: i = iter(v) @@ -393,7 +410,7 @@ class Formatter(TextCodec): if i is None: self.cannot_format(v) else: - self.write_seq('[', ']', i) + self.write_seq('[', ']', i, self.append) def cannot_format(self, v): raise TypeError('Cannot preserves-format: ' + repr(v)) diff --git a/implementations/python/preserves/values.py b/implementations/python/preserves/values.py index 534b076..67be60d 100644 --- a/implementations/python/preserves/values.py +++ b/implementations/python/preserves/values.py @@ -99,7 +99,12 @@ class Record(object): encoder.buffer.append(0x84) def __preserve_write_text__(self, formatter): - formatter.write_seq('<', '>', (self.key,) + self.fields) + formatter.chunks.append('<') + formatter.append(self.key) + for f in self.fields: + formatter.chunks.append(' ') + formatter.append(f) + formatter.chunks.append('>') def __getitem__(self, index): return self.fields[index]