// Path: src/main/java/org/tyrannyofheaven/bukkit/util/ToHMessageUtils.java
// public static String colorize(String text) {
//     if (text == null) return null;
// 
//     // Works best with interned strings
//     String cacheResult = colorizeCache.get(text);
//     if (cacheResult != null) return cacheResult;
// 
//     StringBuilder out = new StringBuilder();
// 
//     ColorizeState state = ColorizeState.TEXT;
//     StringBuilder color = null;
// 
//     for (int i = 0; i < text.length(); i++) {
//         char c = text.charAt(i);
// 
//         if (state == ColorizeState.TEXT) {
//             if (c == '{') {
//                 state = ColorizeState.COLOR_OPEN;
//             }
//             else if (c == '}') {
//                 state = ColorizeState.COLOR_CLOSE;
//             }
//             else if (c == '`') {
//                 state = ColorizeState.COLOR_ESCAPE;
//             }
//             else {
//                 out.append(c);
//             }
//         }
//         else if (state == ColorizeState.COLOR_OPEN) {
//             if (c == '{') { // Escaped bracket
//                 out.append('{');
//                 state = ColorizeState.TEXT;
//             }
//             else if (Character.isUpperCase(c)) {
//                 // First character of color name
//                 color = new StringBuilder();
//                 color.append(c);
//                 state = ColorizeState.COLOR_NAME;
//             }
//             else {
//                 // Invalid
//                 throw new IllegalArgumentException("Invalid color name");
//             }
//         }
//         else if (state == ColorizeState.COLOR_NAME) {
//             if (Character.isUpperCase(c) || c == '_') {
//                 color.append(c);
//             }
//             else if (c == '}') {
//                 ChatColor chatColor = ChatColor.valueOf(color.toString());
//                 out.append(chatColor);
//                 state = ColorizeState.TEXT;
//             }
//             else {
//                 // Invalid
//                 throw new IllegalArgumentException("Invalid color name");
//             }
//         }
//         else if (state == ColorizeState.COLOR_CLOSE) {
//             // Optional, but for sanity's sake, to keep brackets matched
//             if (c == '}') {
//                 out.append('}'); // Collapse to single bracket
//             }
//             else {
//                 out.append('}');
//                 out.append(c);
//             }
//             state = ColorizeState.TEXT;
//         }
//         else if (state == ColorizeState.COLOR_ESCAPE) {
//             out.append(decodeColor(c));
//             state = ColorizeState.TEXT;
//         }
//         else
//             throw new AssertionError("Unknown ColorizeState");
//     }
//         
//     // End of string
//     if (state == ColorizeState.COLOR_CLOSE) {
//         out.append('}');
//     }
//     else if (state != ColorizeState.TEXT) {
//         // Was in the middle of color name
//         throw new IllegalArgumentException("Invalid color name");
//     }
// 
//     cacheResult = out.toString();
//     colorizeCache.putIfAbsent(text, cacheResult);
// 
//     return cacheResult;
// }
// 
// Path: src/main/java/org/tyrannyofheaven/bukkit/util/ToHMessageUtils.java
// public static void sendMessage(CommandSender sender, String format, Object... args) {
//     String message = String.format(format, args);
//     for (String line : message.split("\n")) {
//         sender.sendMessage(line);
//     }
// }
// 
// Path: src/main/java/org/tyrannyofheaven/bukkit/util/ToHStringUtils.java
// public static String delimitedString(String delimiter, Collection<?> coll) {
//     StringBuilder sb = new StringBuilder();
//     for (Iterator<?> i = coll.iterator(); i.hasNext();) {
//         sb.append(i.next());
//         if (i.hasNext())
//             sb.append(delimiter);
//     }
//     return sb.toString();
// }
// 
// Path: src/main/java/org/tyrannyofheaven/bukkit/util/ToHStringUtils.java
// public static boolean hasText(String text) {
//     return text != null && text.trim().length() > 0;
// }


import static org.tyrannyofheaven.bukkit.util.ToHMessageUtils.colorize;
import static org.tyrannyofheaven.bukkit.util.ToHMessageUtils.sendMessage;
import static org.tyrannyofheaven.bukkit.util.ToHStringUtils.delimitedString;
import static org.tyrannyofheaven.bukkit.util.ToHStringUtils.hasText;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.bukkit.Server;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.command.PluginCommand;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
        finally {
            // Remove ThreadLocal to prevent memory leaks
            abortFlags.remove();
        }

        return true;
    }

    /**
     * May be called by command handlers to abort batch processing. Does nothing
     * if the handler was not called within {@link #read(Server, CommandSender, InputStream, boolean, Plugin...)}.
     */
    public static void abortBatchProcessing() {
        if (isBatchProcessing())
            abortFlags.set(Boolean.TRUE);
    }

    /**
     * Tests if current thread is currently running batch commands, e.g.
     * called within {@link #read(Server, CommandSender, InputStream, boolean, Plugin...)}.
     * 
     * @return true if the current thread is running batch commands
     */
    public static boolean isBatchProcessing() {
        return abortFlags.get() != null;
    }

    // Holder for command invocation
    private static class CommandCall {
        
// Path: src/main/java/org/tyrannyofheaven/bukkit/util/ToHMessageUtils.java
// public static String colorize(String text) {
//     if (text == null) return null;
// 
//     // Works best with interned strings
//     String cacheResult = colorizeCache.get(text);
//     if (cacheResult != null) return cacheResult;
// 
//     StringBuilder out = new StringBuilder();
// 
//     ColorizeState state = ColorizeState.TEXT;
//     StringBuilder color = null;
// 
//     for (int i = 0; i < text.length(); i++) {
//         char c = text.charAt(i);
// 
//         if (state == ColorizeState.TEXT) {
//             if (c == '{') {
//                 state = ColorizeState.COLOR_OPEN;
//             }
//             else if (c == '}') {
//                 state = ColorizeState.COLOR_CLOSE;
//             }
//             else if (c == '`') {
//                 state = ColorizeState.COLOR_ESCAPE;
//             }
//             else {
//                 out.append(c);
//             }
//         }
//         else if (state == ColorizeState.COLOR_OPEN) {
//             if (c == '{') { // Escaped bracket
//                 out.append('{');
//                 state = ColorizeState.TEXT;
//             }
//             else if (Character.isUpperCase(c)) {
//                 // First character of color name
//                 color = new StringBuilder();
//                 color.append(c);
//                 state = ColorizeState.COLOR_NAME;
//             }
//             else {
//                 // Invalid
//                 throw new IllegalArgumentException("Invalid color name");
//             }
//         }
//         else if (state == ColorizeState.COLOR_NAME) {
//             if (Character.isUpperCase(c) || c == '_') {
//                 color.append(c);
//             }
//             else if (c == '}') {
//                 ChatColor chatColor = ChatColor.valueOf(color.toString());
//                 out.append(chatColor);
//                 state = ColorizeState.TEXT;
//             }
//             else {
//                 // Invalid
//                 throw new IllegalArgumentException("Invalid color name");
//             }
//         }
//         else if (state == ColorizeState.COLOR_CLOSE) {
//             // Optional, but for sanity's sake, to keep brackets matched
//             if (c == '}') {
//                 out.append('}'); // Collapse to single bracket
//             }
//             else {
//                 out.append('}');
//                 out.append(c);
//             }
//             state = ColorizeState.TEXT;
//         }
//         else if (state == ColorizeState.COLOR_ESCAPE) {
//             out.append(decodeColor(c));
//             state = ColorizeState.TEXT;
//         }
//         else
//             throw new AssertionError("Unknown ColorizeState");
//     }
//         
//     // End of string
//     if (state == ColorizeState.COLOR_CLOSE) {
//         out.append('}');
//     }
//     else if (state != ColorizeState.TEXT) {
//         // Was in the middle of color name
//         throw new IllegalArgumentException("Invalid color name");
//     }
// 
//     cacheResult = out.toString();
//     colorizeCache.putIfAbsent(text, cacheResult);
// 
//     return cacheResult;
// }
// 
// Path: src/main/java/org/tyrannyofheaven/bukkit/util/ToHMessageUtils.java
// public static void sendMessage(CommandSender sender, String format, Object... args) {
//     String message = String.format(format, args);
//     for (String line : message.split("\n")) {
//         sender.sendMessage(line);
//     }
// }
// 
// Path: src/main/java/org/tyrannyofheaven/bukkit/util/ToHStringUtils.java
// public static String delimitedString(String delimiter, Collection<?> coll) {
//     StringBuilder sb = new StringBuilder();
//     for (Iterator<?> i = coll.iterator(); i.hasNext();) {
//         sb.append(i.next());
//         if (i.hasNext())
//             sb.append(delimiter);
//     }
//     return sb.toString();
// }
// 
// Path: src/main/java/org/tyrannyofheaven/bukkit/util/ToHStringUtils.java
// public static boolean hasText(String text) {
//     return text != null && text.trim().length() > 0;
// }


// Path: src/main/java/org/tyrannyofheaven/bukkit/util/command/reader/CommandReader.java
import static org.tyrannyofheaven.bukkit.util.ToHMessageUtils.colorize;
import static org.tyrannyofheaven.bukkit.util.ToHMessageUtils.sendMessage;
import static org.tyrannyofheaven.bukkit.util.ToHStringUtils.delimitedString;
import static org.tyrannyofheaven.bukkit.util.ToHStringUtils.hasText;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.bukkit.Server;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.command.PluginCommand;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;

        finally {
            // Remove ThreadLocal to prevent memory leaks
            abortFlags.remove();
        }

        return true;
    }

    /**
     * May be called by command handlers to abort batch processing. Does nothing
     * if the handler was not called within {@link #read(Server, CommandSender, InputStream, boolean, Plugin...)}.
     */
    public static void abortBatchProcessing() {
        if (isBatchProcessing())
            abortFlags.set(Boolean.TRUE);
    }

    /**
     * Tests if current thread is currently running batch commands, e.g.
     * called within {@link #read(Server, CommandSender, InputStream, boolean, Plugin...)}.
     * 
     * @return true if the current thread is running batch commands
     */
    public static boolean isBatchProcessing() {
        return abortFlags.get() != null;
    }

    // Holder for command invocation
    private static class CommandCall {
        
        private final Command command;