IndentDoc is a document node that wraps a child document and causes every line break produced inside that child to be followed by indentation. The implementation fixes indentation at four spaces. This makes layout preferences composable: place an IndentDoc around a parenthesized expression, continuation, or nested group rather than inserting spaces manually. section 9.3.1
IndentDoc does not itself decide whether an optional break becomes a line break. GroupDoc and the pretty-printing process make that decision; IndentDoc carries the indentation level that applies when a break occurs. The recursive structure is evaluated iteratively by passing indentation through an explicit work stack. section 9.3.3 section 9.3.4
Indenting a formatted call
Wrapping the contents of a call in IndentDoc keeps the argument on the same line when it fits, but moves it four spaces right when the group breaks: Foo.Bar(\n xx + yy * zz). A narrower width can produce nested indentation: Foo.Bar(\n xx +\n yy * zz). section 9.3.1 section 9.3.4
Listing 9.4 A nonrecursive Pretty method
using System.Text;
abstract record class Doc
{
// […]
public string Pretty(int width)
{
var sb = new StringBuilder();
int used = 0; #1
var docs = new Stack<(bool, int, Doc)>(); #2
docs.Push((true, 0, new GroupDoc(this))); #3
while (docs.Count > 0) #4
{
(bool fits, int indent, Doc doc) = docs.Pop(); #5
switch (doc)
{
case TextDoc td:
sb.Append(td.text); #6
used += td.text.Length;
break;
case GroupDoc gd: #7
docs.Push((gd.doc.Fits(width - used), indent, gd.doc));
break;
case IndentDoc id: #8
docs.Push((fits, indent + IndentSpaces, id.doc));
break;
case OptBreakDoc bd:
if (fits) #9
{
sb.Append(bd.text);
used += bd.text.Length;
}
else #10
{
sb.AppendLine();
sb.Append(' ', indent);
used = indent;
}
break;
case ConcatDoc cd: #11
docs.Push((fits, indent, cd.right));
docs.Push((fits, indent, cd.left));
break;
}
}
return sb.ToString();
} }
Inspect the nonrecursive Pretty implementation, where IndentDoc increases the carried indentation value and optional breaks emit that indentation after line breaks. section 9.3.4
