diff --git a/zpp b/zpp index 40776b1..9d40cf6 100755 --- a/zpp +++ b/zpp @@ -51,8 +51,6 @@ def main(args): # So I think it makes the most sense to break the input text by "/*/"? # and then depending on whether a snippet has a newline, we handle it # differently? - # The trouble with that appoarch, is that we won't preserve the indentation. - # I'm not sure that really matters. divisions = entire_input.split("/*/") @@ -64,13 +62,58 @@ def main(args): if passthrough: ostream.write(division); elif "\n" in division: - # this would be a multi-line snippet, so we'll run the source - # altogether and capture the output: + # This would be a multi-line snippet, so we'll run the source + # altogether and capture the output. + # Python is funny about indentation, so we will have to strip off + # the initial left indentation of each of the lines of the snippet. + # So step 1 is figuring out how much indentation we need to remove. + # We'll look at the first line for that. + + # bonus points if we can support tabs too! + + lines = division.split('\n'); + + first_nonempty_line = None; + + # let's find the first non-empty line: + for line in lines: + if line.strip(): + first_nonempty_line = line; + break; + + if first_nonempty_line is None: + print(f"zpp: error! empty snippet!"); + return 1; + + # and just build up the string the whitespace: + indentation = ''; + + for c in first_nonempty_line: + if c.isspace(): + indentation += c + else: + break; + + # now that we know how many spaces to eliminate, let's go through + # each line and remove them. lines of just whitespace can be + # passed through with getting processed. + + source = ""; + + for line in lines: + if not line.strip(): + source += line + '\n'; + elif line.startswith(indentation): + source += line[len(indentation):] + '\n'; + else: + print(f"zpp: error! mixed indentation in snippet!"); + return 1; + real_stdout = sys.stdout sys.stdout = captured_stdout = io.StringIO() - eval(compile(division, "", "exec"), snippet_globals); + eval(compile(source, "", "exec"), snippet_globals); sys.stdout = real_stdout