From 27d272ade04125bb711aac508f8d8b6ca034234f Mon Sep 17 00:00:00 2001 From: Jakob Stoklund Olesen Date: Fri, 7 Jul 2017 14:32:13 -0700 Subject: [PATCH] Add a fmt.multi_line() method to srcgen.Formatter. Write out multiple code lines from a single string after stripping a common indentation. Also use this for doc_comment(). --- lib/cretonne/meta/srcgen.py | 43 ++++++++++++++++++++++++++++++++++--- 1 file changed, 40 insertions(+), 3 deletions(-) diff --git a/lib/cretonne/meta/srcgen.py b/lib/cretonne/meta/srcgen.py index d91ecc4ab2..f0f7931ea1 100644 --- a/lib/cretonne/meta/srcgen.py +++ b/lib/cretonne/meta/srcgen.py @@ -8,7 +8,6 @@ source code. from __future__ import absolute_import import sys import os -import re try: from typing import Any, List # noqa @@ -130,6 +129,12 @@ class Formatter(object): # type: (str, *Any) -> None self.line(fmt.format(*args)) + def multi_line(self, s): + # type: (str) -> None + """Add one or more lines after stripping common indentation.""" + for l in parse_multiline(s): + self.line(l) + def comment(self, s): # type: (str) -> None """Add a comment line.""" @@ -138,5 +143,37 @@ class Formatter(object): def doc_comment(self, s): # type: (str) -> None """Add a (multi-line) documentation comment.""" - s = re.sub('^', self.indent + '/// ', s, flags=re.M) + '\n' - self.lines.append(s) + for l in parse_multiline(s): + self.line('/// ' + l if l else '///') + + +def _indent(s): + # type: (str) -> int + """ + Compute the indentation of s, or None of an empty line. + + Example: + >>> _indent("foo") + 0 + >>> _indent(" bar") + 4 + >>> _indent(" ") + >>> _indent("") + """ + t = s.lstrip() + return len(s) - len(t) if t else None + + +def parse_multiline(s): + # type: (str) -> List[str] + """ + Given a multi-line string, split it into a sequence of lines after + stripping a common indentation. This is useful for strings defined with doc + strings: + >>> parse_multiline('\\n hello\\n world\\n') + [None, 'hello', 'world'] + """ + lines = s.splitlines() + indents = list(i for i in (_indent(l) for l in lines) if i) + indent = min(indents) if indents else 0 + return list(l[indent:] if len(l) > indent else None for l in lines)