private void format(String expression, int indent, StringBuilder b) {
        if (expression.isEmpty()) return;
        expression = appendFirstColumn(expression, b);

        Markup next = Markup.next(expression);

        appendIndent( ! next.isClose() || next.position() > 0 ? indent : indent - 2, b);

        int endOfBalancedChunk = endOfBalancedChunk(expression, Math.max(0, secondColumnLength - indent));
        if (next.isEmpty()) {
            b.append(expression);
        }
        else if (endOfBalancedChunk > 0) {
            b.append(expression, 0, endOfBalancedChunk + 1).append("\n");
            format(expression.substring(endOfBalancedChunk + 1), indent, b);
        }
        else if (next.isComma()) {
            b.append(expression, 0, next.position() + 1).append("\n");
            format(expression.substring(next.position() + 1), indent, b);
        }
        else {
            if ( next.isClose() && next.position() > 0) { // content before end parenthesis: content, newline, then end parenthesis
                b.append(expression, 0, next.position()).append("\n");
                appendFirstColumn(")", b);
                appendIndent(indent - 2, b);
                b.append(")\n");
            }
            else {
                b.append(expression, 0, next.position() + 1).append("\n");
            }
            format(expression.substring(next.position() + 1), indent + (next.isOpen() ? indentUnit : -indentUnit), b);
        }
    }
The desired size of the second column (or the entire line if no first column),
or 0 to split into multiple lines as much as possible.
Setting this collects larger chunks to one line across markup
but will not split too long lines that have no markup.
vespajlib/src/main/java/com/yahoo/text/ExpressionFormatter.java