From 23ea10a6e7d021d7dfd365f54baae56170107601 Mon Sep 17 00:00:00 2001
From: David Gregory <2992938+DavidGregory084@users.noreply.github.com>
Date: Sat, 8 Jun 2024 15:03:01 +0100
Subject: [PATCH] Don't layout an entire alternative before deciding whether it
fits
---
.../com/opencastsoftware/prettier4j/Doc.java | 53 ++++++-------------
1 file changed, 15 insertions(+), 38 deletions(-)
diff --git a/src/main/java/com/opencastsoftware/prettier4j/Doc.java b/src/main/java/com/opencastsoftware/prettier4j/Doc.java
index 9b3657f..5a2168a 100644
--- a/src/main/java/com/opencastsoftware/prettier4j/Doc.java
+++ b/src/main/java/com/opencastsoftware/prettier4j/Doc.java
@@ -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.
- *
- * 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 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
@@ -1708,15 +1676,24 @@ static boolean fits(int remaining, Queue entries) {
* @return the entries of the chosen layout.
*/
private static Queue chooseLayout(Doc left, Doc right, RenderOptions options, Doc margin, int indent, int position) {
- Queue leftEntries = layout(left, options, margin, indent, position);
+ Deque inQueue = new ArrayDeque<>();
+ Queue 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;
}
/**