Skip to content

Instantly share code, notes, and snippets.

@FedericoPonzi
Last active August 29, 2025 08:54
Show Gist options
  • Save FedericoPonzi/9273d951189ab99ad5a7aba92ad0fc69 to your computer and use it in GitHub Desktop.
Save FedericoPonzi/9273d951189ab99ad5a7aba92ad0fc69 to your computer and use it in GitHub Desktop.
Two fixes:
1. Align elimination
Use the current column as the new indent. Do not emit spaces or push the original entry.
```java
} else if (entryDoc instanceof Align) {
Align alignDoc = (Align) entryDoc;
int newIndent = position; // anchor at current column
inQueue.addFirst(entry(newIndent, entryMargin, alignDoc.doc()));
}
```
2. LineOr handling
You are double-counting indentation: you set position to entryIndent and also enqueue indent spaces. Reset to column 0 and let margin + spaces advance position.
```java
} else if (entryDoc instanceof LineOr) {
// Start a new line at column 0; margin + spaces will advance position
position = 0;
// Note reverse order: push spaces first, then margin, so margin is processed first
if (entryIndent > 0) {
String indentSpaces = Indents.get(entryIndent);
inQueue.addFirst(entry(entryIndent, entryMargin, text(indentSpaces)));
}
inQueue.addFirst(entry(entryIndent, entryMargin, entryMargin));
outQueue.add(topEntry);
}
```
How to use Align in your DisjListConstruct
Align once for the whole block, not after every append. Ensure the parent appends the block immediately after the colon so the anchor column is correct.
```java
public class DisjListConstruct implements TlaConstruct {
@Override public String getName() { return "N_DisjList"; }
@Override public int getSupportedNodeKind() { return NodeKind.DISJ_LIST.getId(); }
@Override
public Doc buildDoc(TreeNode node, ConstructContext context, int indentSize) {
var z = node.zero();
assert z != null && z.length > 0;
List<Doc> parts = Arrays.stream(z).map(context::buildChild).collect(Collectors.toList());
Doc body = parts.get(0);
for (int i = 1; i < parts.size(); i++) {
body = body.appendLine(parts.get(i));
}
// Align the entire block relative to the current column at the call site
return Doc.group(body.align());
}
}
```
At the call site for your example, build like this so Align anchors right after the colon:
```java
Doc comp =
text("{ x \\in 1 .. max : ")
.append(disjListDoc) // disjListDoc is the result of DisjListConstruct
.append(text(" }"));
return Doc.group(comp);
```
What to check next
* If the colon and the list are produced by different visitors, ensure the parent composes them in this order: colon + space, then the aligned list. If the list is wrapped in additional nodes after the colon, Align may capture the wrong column.
* Add a unit test with a narrow width to force a break and assert the two lines of the predicates start in the same column.
* If you need a hanging indent after the colon (e.g., +2 spaces), introduce a helper hang(by, d) = align(indent(by, d)) and use hang(2, disjListBlock).
/**
* Represents a {@link Doc} aligned to the current column position.
* When a new line occurs within this document, subsequent lines will be
* indented to align with the column position where this document started.
*/
public static class Align extends Doc {
private final Doc doc;
protected Align(Doc doc) {
this.doc = doc;
}
public Doc doc() {
return doc;
}
@Override
Doc flatten() {
return new Align(doc.flatten());
}
@Override
boolean hasParams() {
return doc.hasParams();
}
@Override
boolean hasLineSeparators() {
return doc.hasLineSeparators();
}
@Override
public Doc bind(String name, Doc value) {
return new Align(doc.bind(name, value));
}
@Override
public Doc bind(Map<String, Doc> bindings) {
return new Align(doc.bind(bindings));
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Align align = (Align) o;
return Objects.equals(doc, align.doc);
}
@Override
public int hashCode() {
return Objects.hash(doc);
}
@Override
public String toString() {
return "Align[" +
"doc=" + doc +
']';
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment