Skip to content

Commit

Permalink
Don't layout an entire alternative before deciding whether it fits
Browse files Browse the repository at this point in the history
  • Loading branch information
DavidGregory084 committed Jun 8, 2024
1 parent 03fd98d commit 23ea10a
Showing 1 changed file with 15 additions and 38 deletions.
53 changes: 15 additions & 38 deletions src/main/java/com/opencastsoftware/prettier4j/Doc.java
Original file line number Diff line number Diff line change
Expand Up @@ -1662,38 +1662,6 @@ private static Entry entry(int indent, Doc margin, Doc doc) {
return new Entry(indent, margin, doc);
}

/**
* Inspects the remaining space on the current line and the entries in the
* current layout to see whether they fit onto the current line.
* <p>
* It's only necessary to inspect entries up to the next line break.
*
* @param remaining the remaining space on the current line.
* @param entries the entries we'd like to fit onto this line
* @return true if we can fit all {@link Doc.Text entries} up to the
* next line break into the remaining characters of the current line.
*/
static boolean fits(int remaining, Queue<Entry> entries) {
if (remaining < 0)
return false;

for (Entry entry : entries) {
Doc entryDoc = entry.doc();

// layout reduces Doc to Text, LineOr, Escape and Reset
if (entryDoc instanceof Text) {
Text textDoc = (Text) entryDoc;
remaining -= textDoc.text().length();
if (remaining < 0)
return false;
} else if (entryDoc instanceof LineOr) {
return true;
} // No need to handle Escape or Reset as they are effectively zero-length
}

return true;
}

/**
* Choose between two layouts at the current rendering width, indentation level
* and line position, choosing the {@code left} document if it fits and the
Expand All @@ -1708,15 +1676,24 @@ static boolean fits(int remaining, Queue<Entry> entries) {
* @return the entries of the chosen layout.
*/
private static Queue<Entry> chooseLayout(Doc left, Doc right, RenderOptions options, Doc margin, int indent, int position) {
Queue<Entry> leftEntries = layout(left, options, margin, indent, position);
Deque<Entry> inQueue = new ArrayDeque<>();
Queue<Entry> outQueue = new ArrayDeque<>();

int remaining = options.lineWidth() - position;
inQueue.add(entry(indent, margin, left));

if (fits(remaining, leftEntries)) {
return leftEntries;
} else {
return layout(right, options, margin, indent, position);
while (!inQueue.isEmpty()) {
Entry topEntry = inQueue.removeFirst();
position = layoutEntry(options, inQueue, outQueue, topEntry, position);

int remaining = options.lineWidth() - position;

if (remaining < 0) {
// The new entry doesn't fit, so use the other layout
return layout(right, options, margin, indent, position);
}
}

return outQueue;
}

/**
Expand Down

0 comments on commit 23ea10a

Please sign in to comment.