SPIGOT-6705: Re-print tab completion "Display all" message in console, when another message is being logged

By: DerFrZocker <derrieple@gmail.com>
This commit is contained in:
CraftBukkit/Spigot
2024-04-07 11:54:28 +10:00
parent 84d43ef379
commit d54bcadd91
3 changed files with 85 additions and 13 deletions

View File

@@ -0,0 +1,53 @@
package org.bukkit.craftbukkit.util;
import java.io.IOException;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import jline.console.ConsoleReader;
import jline.console.completer.CompletionHandler;
/**
* SPIGOT-6705: Make sure we print the display line again on tab completion, so that the user does not get stuck on it
* e.g. The user needs to press y / n to continue
*/
public class TerminalCompletionHandler implements CompletionHandler {
private final TerminalConsoleWriterThread writerThread;
private final CompletionHandler delegate;
public TerminalCompletionHandler(TerminalConsoleWriterThread writerThread, CompletionHandler delegate) {
this.writerThread = writerThread;
this.delegate = delegate;
}
@Override
public boolean complete(ConsoleReader reader, List<CharSequence> candidates, int position) throws IOException {
// First check normal list, so that we do not unnecessarily create a new HashSet if the not distinct list is already lower
if (candidates.size() <= reader.getAutoprintThreshold()) {
return delegate.complete(reader, candidates, position);
}
Set<CharSequence> distinct = new HashSet<>(candidates);
if (distinct.size() <= reader.getAutoprintThreshold()) {
return delegate.complete(reader, candidates, position);
}
writerThread.setCompletion(distinct.size());
// FIXME: Potential concurrency issue, when terminal writer prints the display message before the delegate does it
// resulting in two display message being present, until a new message gets logged or the user presses y / n
// But the probability of this happening are probably lower than the effort needed to fix this
// And seeing the display message at all should be a higher priority than seeing it two times in rare cases.
boolean result = delegate.complete(reader, candidates, position);
writerThread.setCompletion(-1);
// draw line to prevent concurrency issue,
// where terminal write would print the display message between delegate#complete finished and the completion set back to -1
// Resulting in the display message being present even after pressing y / n
reader.drawLine();
reader.flush();
return result;
}
}

View File

@@ -3,16 +3,21 @@ package org.bukkit.craftbukkit.util;
import com.mojang.logging.LogQueues;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Locale;
import java.util.ResourceBundle;
import java.util.logging.Level;
import java.util.logging.Logger;
import jline.console.ConsoleReader;
import jline.console.completer.CandidateListCompletionHandler;
import org.bukkit.craftbukkit.Main;
import org.fusesource.jansi.Ansi;
import org.fusesource.jansi.Ansi.Erase;
public class TerminalConsoleWriterThread extends Thread {
private final ResourceBundle bundle = ResourceBundle.getBundle(CandidateListCompletionHandler.class.getName(), Locale.getDefault());
private final ConsoleReader reader;
private final OutputStream output;
private volatile int completion = -1;
public TerminalConsoleWriterThread(OutputStream output, ConsoleReader reader) {
super("TerminalConsoleWriter");
@@ -45,6 +50,12 @@ public class TerminalConsoleWriterThread extends Thread {
} catch (Throwable ex) {
reader.getCursorBuffer().clear();
}
if (completion > -1) {
// SPIGOT-6705: Make sure we print the display line again on tab completion, so that the user does not get stuck on it
reader.print(String.format(bundle.getString("DISPLAY_CANDIDATES"), completion));
}
reader.flush();
} else {
output.write(message.getBytes());
@@ -55,4 +66,8 @@ public class TerminalConsoleWriterThread extends Thread {
}
}
}
void setCompletion(int completion) {
this.completion = completion;
}
}