From 4f18b70047255bbd18202656c6e95333ec9cac58 Mon Sep 17 00:00:00 2001
From: Phillip Schichtel <quick_wango@code-infection.de>
Date: Fri, 5 Jul 2013 21:55:00 +1000
Subject: [PATCH] Console Command Completion

changed exception handling
wrapped the tab completion in a waitable to sync it with the main thread
Implement command tab completion in the console. Adds BUKKIT-4168

Even though JLine provides an API for tab completion, there was still now tab
completion for console commands.
This commit implements tab completion in the console by providing the
ConsoleReader with a Completer implementation.

diff --git a/src/main/java/net/minecraft/server/PlayerList.java b/src/main/java/net/minecraft/server/PlayerList.java
index 971cfa5..7cf2a94 100644
--- a/src/main/java/net/minecraft/server/PlayerList.java
+++ b/src/main/java/net/minecraft/server/PlayerList.java
@@ -17,6 +17,7 @@ import java.util.Map.Entry;
 import org.bukkit.craftbukkit.CraftServer;
 import org.bukkit.craftbukkit.CraftWorld;
 import org.bukkit.craftbukkit.chunkio.ChunkIOExecutor;
+import org.bukkit.craftbukkit.command.ConsoleCommandCompleter;
 
 import org.bukkit.Bukkit;
 import org.bukkit.Location;
@@ -55,6 +56,7 @@ public abstract class PlayerList {
     public PlayerList(MinecraftServer minecraftserver) {
         minecraftserver.server = new CraftServer(minecraftserver, this);
         minecraftserver.console = org.bukkit.craftbukkit.command.ColouredConsoleSender.getInstance();
+        minecraftserver.reader.addCompleter(new ConsoleCommandCompleter(minecraftserver.server));
         this.cserver = minecraftserver.server;
         // CraftBukkit end
 
diff --git a/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java b/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java
new file mode 100644
index 0000000..b108bd1
--- /dev/null
+++ b/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java
@@ -0,0 +1,46 @@
+package org.bukkit.craftbukkit.command;
+
+import jline.console.completer.Completer;
+import org.bukkit.craftbukkit.CraftServer;
+import org.bukkit.craftbukkit.util.Waitable;
+
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+import java.util.logging.Level;
+
+public class ConsoleCommandCompleter implements Completer {
+    private final CraftServer server;
+
+    public ConsoleCommandCompleter(CraftServer server) {
+        this.server = server;
+    }
+
+    public int complete(final String buffer, final int cursor, final List<CharSequence> candidates) {
+        Waitable<Integer> waitable = new Waitable<Integer>() {
+            @Override
+            protected Integer evaluate() {
+                List<String> offers = server.getCommandMap().tabComplete(server.getConsoleSender(), buffer);
+                if (offers == null) {
+                    return cursor;
+                }
+                candidates.addAll(offers);
+
+                final int lastSpace = buffer.lastIndexOf(' ');
+                if (lastSpace == -1) {
+                    return cursor - buffer.length();
+                } else {
+                    return cursor - (buffer.length() - lastSpace - 1);
+                }
+            }
+        };
+        this.server.getServer().processQueue.add(waitable);
+        try {
+            return waitable.get();
+        } catch (ExecutionException e) {
+            this.server.getLogger().log(Level.WARNING, "Unhandled exception when tab completing", e);
+        } catch (InterruptedException e) {
+            Thread.currentThread().interrupt();
+        }
+        return cursor;
+    }
+}
-- 
1.8.1.2