diff options
author | David Robillard <d@drobilla.net> | 2010-09-15 03:03:17 +0000 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2010-09-15 03:03:17 +0000 |
commit | c5e2f5dbb8922ba9bc5baa8e3194be89cb64f367 (patch) | |
tree | 16f083f852e0cf38d2c779bf881b0a33fc69122c /src | |
parent | 8338b52abc0e5a1c0893526bde2d347f1891773e (diff) | |
download | resp-c5e2f5dbb8922ba9bc5baa8e3194be89cb64f367.tar.gz resp-c5e2f5dbb8922ba9bc5baa8e3194be89cb64f367.tar.bz2 resp-c5e2f5dbb8922ba9bc5baa8e3194be89cb64f367.zip |
Better pretty printer.
git-svn-id: http://svn.drobilla.net/resp/resp@269 ad02d1e2-f140-0410-9f75-f8b11f17cedd
Diffstat (limited to 'src')
-rw-r--r-- | src/pprint.cpp | 107 |
1 files changed, 87 insertions, 20 deletions
diff --git a/src/pprint.cpp b/src/pprint.cpp index 391609a..76796d7 100644 --- a/src/pprint.cpp +++ b/src/pprint.cpp @@ -73,34 +73,101 @@ operator<<(ostream& out, const AST* ast) return out << "?"; } +enum TupleStyle { + STYLE_ONE_LINE, // Entire tuple printed on one line + STYLE_ALIGN, // Align all elements aligned after opening '(' + STYLE_CALL // Call with all arguments aligned after head +}; + +static bool +can_one_line(const AST* ast, const unsigned max_width, unsigned& width, unsigned& depth) +{ + static const unsigned MAX_DEPTH = 3; + + ostringstream ss; + ss << ast; + if ((width += ss.str().length()) >= max_width) + return false; + + const ATuple* tup = ast->to<const ATuple*>(); + if (tup) { + if (++depth >= MAX_DEPTH) + return false; + + for (ATuple::const_iterator i = tup->begin(); i != tup->end(); ++i) { + ostringstream ss; + ss << *i; + width += ss.str().length(); + if (!can_one_line(*i, max_width, width, depth)) + return false; + } + } + + return true; +} + +static TupleStyle +tuple_style(const ATuple* tup, const unsigned max_width, unsigned& indent) +{ + unsigned depth = 0; + unsigned width = indent; + if (can_one_line(tup, max_width, width, depth)) + return STYLE_ONE_LINE; + + if (tup->to<const ADef*>() || tup->to<const AFn*>()) { + indent += 2; + return STYLE_CALL; + } + + if (tup->to<const ACall*>()) { + indent += tup->head()->str().length() + 1; + return STYLE_CALL; + } + + return STYLE_ALIGN; +} + +static void +newline(ostream& out, unsigned indent) +{ + out << endl; + for (unsigned i = 0; i < indent; ++i) + out << " "; +} + void pprint_internal(ostream& out, const AST* ast, unsigned indent) { const ATuple* tup = ast->to<const ATuple*>(); - if (tup && !tup->empty()) { - ATuple::const_iterator i = tup->begin() + 1; - const string head = tup->head()->str(); - const ASymbol* headSym = tup->head()->to<const ASymbol*>(); + if (tup) { out << "("; - pprint_internal(out, tup->head(), indent); - unsigned child_indent = indent; - if (tup->size() > 1) { - out << " "; - if (headSym && (headSym->cppstr == "fn" || headSym->cppstr == "def")) { - out << *i; - child_indent = indent + 2; - } else { - child_indent += head.length() + 2; - pprint_internal(out, *i, child_indent); + unsigned child_indent = indent + 1; + ATuple::const_iterator i = tup->begin(); + if (i != tup->end()) { + const TupleStyle style = tuple_style(tup, 80, child_indent); + pprint_internal(out, *i++, indent + 1); // Print head + switch (style) { + case STYLE_ONE_LINE: + while (i != tup->end()) + out << " " << *i++; + break; + case STYLE_ALIGN: + while (i != tup->end()) { + newline(out, indent + 1); + pprint_internal(out, *i++, child_indent); + } + break; + case STYLE_CALL: + out << " "; + pprint_internal(out, *i, child_indent); // Print first argument + while (++i != tup->end()) { + newline(out, child_indent); + pprint_internal(out, *i, child_indent); + } + break; } } - while (++i != tup->end()) { - out << endl << string().insert(0, child_indent, ' '); - pprint_internal(out, *i, child_indent); - } out << ")"; - if (headSym && (headSym->cppstr == "fn" || headSym->cppstr == "def")) - out << endl << string().insert(0, indent + 2, ' '); } else { out << ast; } |