diff options
Diffstat (limited to 'base/src/main/java/bjc/utils/cli')
| -rw-r--r-- | base/src/main/java/bjc/utils/cli/CLICommander.java | 76 | ||||
| -rw-r--r-- | base/src/main/java/bjc/utils/cli/Command.java | 13 | ||||
| -rw-r--r-- | base/src/main/java/bjc/utils/cli/CommandHandler.java | 13 | ||||
| -rw-r--r-- | base/src/main/java/bjc/utils/cli/CommandHelp.java | 9 | ||||
| -rw-r--r-- | base/src/main/java/bjc/utils/cli/CommandMode.java | 47 | ||||
| -rw-r--r-- | base/src/main/java/bjc/utils/cli/DelegatingCommand.java | 17 | ||||
| -rw-r--r-- | base/src/main/java/bjc/utils/cli/GenericCommand.java | 23 | ||||
| -rw-r--r-- | base/src/main/java/bjc/utils/cli/GenericCommandMode.java | 233 | ||||
| -rw-r--r-- | base/src/main/java/bjc/utils/cli/GenericHelp.java | 24 | ||||
| -rw-r--r-- | base/src/main/java/bjc/utils/cli/NullHelp.java | 3 | ||||
| -rw-r--r-- | base/src/main/java/bjc/utils/cli/objects/BlockReaderCLI.java | 134 | ||||
| -rw-r--r-- | base/src/main/java/bjc/utils/cli/objects/Command.java | 84 | ||||
| -rw-r--r-- | base/src/main/java/bjc/utils/cli/objects/DefineCLI.java | 10 |
13 files changed, 409 insertions, 277 deletions
diff --git a/base/src/main/java/bjc/utils/cli/CLICommander.java b/base/src/main/java/bjc/utils/cli/CLICommander.java index cccb255..1504002 100644 --- a/base/src/main/java/bjc/utils/cli/CLICommander.java +++ b/base/src/main/java/bjc/utils/cli/CLICommander.java @@ -10,19 +10,14 @@ import java.util.Scanner; * Runs a CLI interface from the provided set of streams. * * @author ben - * */ public class CLICommander { - /* - * The streams used for input and normal/error output. - */ + /* The streams used for input and normal/error output. */ private final InputStream input; private final OutputStream output; private final OutputStream error; - /* - * The command mode to start execution in. - */ + /* The command mode to start execution in. */ private CommandMode initialMode; /** @@ -30,38 +25,35 @@ public class CLICommander { * * @param input * The stream to get user input from. + * * @param output * The stream to send normal output to. + * * @param error * The stream to send error output to. */ public CLICommander(final InputStream input, final OutputStream output, final OutputStream error) { - if (input == null) - throw new NullPointerException("Input stream must not be null"); - else if (output == null) - throw new NullPointerException("Output stream must not be null"); - else if (error == null) throw new NullPointerException("Error stream must not be null"); + if (input == null) throw new NullPointerException("Input stream must not be null"); + else if (output == null) throw new NullPointerException("Output stream must not be null"); + else if (error == null) throw new NullPointerException("Error stream must not be null"); this.input = input; this.output = output; this.error = error; } - /** - * Start handling commands from the given input stream. - */ + /** Start handling commands from the given input stream. */ public void runCommands() { - /* - * Setup output streams. - */ + /* Setup output streams. */ final PrintStream normalOutput = new PrintStream(output); - final PrintStream errorOutput = new PrintStream(error); + final PrintStream errorOutput = new PrintStream(error); /* * Set up input streams. * - * We're suppressing the warning because we might use the input - * stream multiple times. + * We're suppressing the warning about a potentially leaked + * resource because we might use the input stream multiple + * times. */ @SuppressWarnings("resource") final Scanner inputSource = new Scanner(input); @@ -69,55 +61,55 @@ public class CLICommander { /* * The mode currently being used to handle commands. * - * Used to preserve the initial mode. + * Used to preserve the initial mode, so that a mode can be + * invoked more than once. */ CommandMode currentMode = initialMode; + /* The number of the command we are executing. */ + int comno = 1; /* - * Process commands until we're told to stop. + * Process commands until we're told to stop, by the mode being + * set to null. */ while (currentMode != null) { /* - * Print out the command prompt, using a custom prompt - * if one is specified. + * Print out the command prompt. + * + * Use a custom prompt if one is specified. */ if (currentMode.isCustomPromptEnabled()) { normalOutput.print(currentMode.getCustomPrompt()); } else { - normalOutput.print(currentMode.getName() + ">> "); + normalOutput.printf("%s (%d)>> ", currentMode.getName(), comno); + + comno += 1; } - /* - * Read in a command. - */ + /* Read in a command. */ final String currentLine = inputSource.nextLine(); - /* - * Handle commands we can handle. - */ + /* Handle commands we can handle in this mode. */ if (currentMode.canHandle(currentLine)) { final String[] commandTokens = currentLine.split(" "); - String[] commandArgs = null; + String[] commandArgs = null; final int argCount = commandTokens.length; - /* - * Parse args if they are present. - */ + /* Parse args if they are present. */ if (argCount > 1) { commandArgs = Arrays.copyOfRange(commandTokens, 1, argCount); } - /* - * Process command. - */ + /* Process command. */ currentMode = currentMode.process(commandTokens[0], commandArgs); } else { - errorOutput.print("Error: Unrecognized command " + currentLine); + errorOutput.printf("Error: Unrecognized command '%s' (no. %d)\n", + currentLine, comno); } } - normalOutput.print("Exiting now."); + normalOutput.printf("Exiting now (ran %d commands).\n", comno); } /** @@ -127,7 +119,7 @@ public class CLICommander { * The initial command mode to use. */ public void setInitialCommandMode(final CommandMode initialMode) { - if (initialMode == null) throw new NullPointerException("Initial mode must be non-zero"); + if (initialMode == null) throw new NullPointerException("Initial mode must be non-null"); this.initialMode = initialMode; } diff --git a/base/src/main/java/bjc/utils/cli/Command.java b/base/src/main/java/bjc/utils/cli/Command.java index 02bc061..5969298 100644 --- a/base/src/main/java/bjc/utils/cli/Command.java +++ b/base/src/main/java/bjc/utils/cli/Command.java @@ -4,34 +4,37 @@ package bjc.utils.cli; * Represents a command that can be invoked from a {@link CommandMode} * * @author ben - * */ public interface Command { /** * Create a command that serves as an alias to this one * - * @return A command that serves as an alias to this one + * @return + * A command that serves as an alias to this one */ Command aliased(); /** * Get the handler that executes this command * - * @return The handler that executes this command + * @return + * The handler that executes this command */ CommandHandler getHandler(); /** * Get the help entry for this command * - * @return The help entry for this command + * @return + * The help entry for this command */ CommandHelp getHelp(); /** * Check if this command is an alias of another command * - * @return Whether or not this command is an alias of another + * @return + * Whether or not this command is an alias of another */ default boolean isAlias() { return false; diff --git a/base/src/main/java/bjc/utils/cli/CommandHandler.java b/base/src/main/java/bjc/utils/cli/CommandHandler.java index 2548248..fd40aa3 100644 --- a/base/src/main/java/bjc/utils/cli/CommandHandler.java +++ b/base/src/main/java/bjc/utils/cli/CommandHandler.java @@ -3,20 +3,21 @@ package bjc.utils.cli; import java.util.function.Function; /** - * A handler for a command + * A handler for a command. * * @author ben - * */ @FunctionalInterface public interface CommandHandler extends Function<String[], CommandMode> { /** - * Execute this command + * Execute this command. * * @param args - * The arguments for this command - * @return The command mode to switch to after this command, or null to - * stop executing commands + * The arguments for this command. + * + * @return + * The command mode to switch to after this command, or null to + * stop executing commands. */ default CommandMode handle(final String[] args) { return this.apply(args); diff --git a/base/src/main/java/bjc/utils/cli/CommandHelp.java b/base/src/main/java/bjc/utils/cli/CommandHelp.java index 86567a0..90ee404 100644 --- a/base/src/main/java/bjc/utils/cli/CommandHelp.java +++ b/base/src/main/java/bjc/utils/cli/CommandHelp.java @@ -4,13 +4,13 @@ package bjc.utils.cli; * Interface for the help entry for a command * * @author ben - * */ public interface CommandHelp { /** * Get the description of a command. * - * @return The description of a command + * @return + * The description of a command */ String getDescription(); @@ -20,12 +20,13 @@ public interface CommandHelp { * A summary line should consist of a string of the following format * * <pre> - * "<command-name>\t<command-summary>" + * "<command-name&rt;\t<command-summary&rt;" * </pre> * * where anything in angle brackets should be filled in. * - * @return The summary line line for a command + * @return + * The summary line line for a command */ String getSummary(); } diff --git a/base/src/main/java/bjc/utils/cli/CommandMode.java b/base/src/main/java/bjc/utils/cli/CommandMode.java index 39c72fc..4107717 100644 --- a/base/src/main/java/bjc/utils/cli/CommandMode.java +++ b/base/src/main/java/bjc/utils/cli/CommandMode.java @@ -2,64 +2,71 @@ package bjc.utils.cli; /** * A mode for determining the commands that are valid to enter, and then - * handling those commands + * handling those commands. * * @author ben - * */ public interface CommandMode extends Comparable<CommandMode> { /** - * Check to see if this mode can handle the specified command + * Check to see if this mode can handle the specified command. * * @param command - * The command to check - * @return Whether or not this mode can handle the command. It is - * assumed not by default + * The command to check. + * + * @return + * Whether or not this mode can handle the command. It is + * assumed not by default. */ default boolean canHandle(final String command) { return false; }; /** - * Get the custom prompt for this mode + * Get the custom prompt for this mode. * - * @return the custom prompt for this mode + * @return + * The custom prompt for this mode. * * @throws UnsupportedOperationException - * if this mode doesn't support a custom prompt + * If this mode doesn't support a custom prompt. */ default String getCustomPrompt() { throw new UnsupportedOperationException("This mode doesn't support a custom prompt"); } /** - * Get the name of this command mode + * Get the name of this command mode. * - * @return The name of this command mode, which is the empty string by - * default + * @return + * The name of this command mode, or a default string if one isn't + * specified. */ public default String getName() { - return ""; + return "(anonymous)"; } /** - * Check if this mode uses a custom prompt + * Check if this mode uses a custom prompt. * - * @return Whether or not this mode uses a custom prompt + * @return + * Whether or not this mode uses a custom prompt. */ default boolean isCustomPromptEnabled() { return false; } /** - * Process a command in this mode + * Process a command in this mode.. * * @param command - * The command to process + * The command to process. + * * @param args - * A list of arguments to the command - * @return The command mode to use for the next command. Defaults to - * returning this, and doing nothing else + * A list of arguments to the command. + * + * @return + * The command mode to use for the next command. Defaults to doing + * nothing, and staying in the current mode. */ default CommandMode process(final String command, final String[] args) { return this; diff --git a/base/src/main/java/bjc/utils/cli/DelegatingCommand.java b/base/src/main/java/bjc/utils/cli/DelegatingCommand.java index acaa3a6..9e882c2 100644 --- a/base/src/main/java/bjc/utils/cli/DelegatingCommand.java +++ b/base/src/main/java/bjc/utils/cli/DelegatingCommand.java @@ -4,12 +4,9 @@ package bjc.utils.cli; * A class for a command that delegates to another command. * * @author ben - * */ class DelegatingCommand implements Command { - /* - * The command to delegate to. - */ + /* The command to delegate to. */ private final Command delegate; /** @@ -49,16 +46,6 @@ class DelegatingCommand implements Command { */ @Override public String toString() { - final StringBuilder builder = new StringBuilder(); - builder.append("DelegatingCommand ["); - - if (delegate != null) { - builder.append("delegate="); - builder.append(delegate); - } - - builder.append("]"); - - return builder.toString(); + return String.format("DelegatingCommand [delegate=%s]", delegate); } } diff --git a/base/src/main/java/bjc/utils/cli/GenericCommand.java b/base/src/main/java/bjc/utils/cli/GenericCommand.java index 4ae4dea..89539a4 100644 --- a/base/src/main/java/bjc/utils/cli/GenericCommand.java +++ b/base/src/main/java/bjc/utils/cli/GenericCommand.java @@ -4,17 +4,12 @@ package bjc.utils.cli; * Generic command implementation. * * @author ben - * */ public class GenericCommand implements Command { - /* - * The behavior for invoking the command. - */ + /* The behavior for invoking the command. */ private final CommandHandler handler; - /* - * The help for the command. - */ + /* The help for the command. */ private CommandHelp help; /** @@ -22,9 +17,11 @@ public class GenericCommand implements Command { * * @param handler * The handler to use for the command. + * * @param description * The description of the command. May be null, in which * case a default is provided. + * * @param help * The detailed help message for the command. May be * null, in which case the description is repeated for @@ -69,16 +66,6 @@ public class GenericCommand implements Command { */ @Override public String toString() { - final StringBuilder builder = new StringBuilder(); - builder.append("GenericCommand ["); - - if (help != null) { - builder.append("help="); - builder.append(help); - } - - builder.append("]"); - - return builder.toString(); + return String.format("GenericCommand [help=%s]", help); } } diff --git a/base/src/main/java/bjc/utils/cli/GenericCommandMode.java b/base/src/main/java/bjc/utils/cli/GenericCommandMode.java index 8764537..e24a17b 100644 --- a/base/src/main/java/bjc/utils/cli/GenericCommandMode.java +++ b/base/src/main/java/bjc/utils/cli/GenericCommandMode.java @@ -8,103 +8,91 @@ import bjc.utils.funcdata.FunctionalMap; import bjc.utils.funcdata.IMap; /** - * A general command mode, with a customizable set of commands + * A general command mode, with a customizable set of commands. * * There is a small set of commands which is handled by default. The first is * 'list', which lists all the commands the user can input. The second is - * 'alias', which allows the user to bind a new name to a command + * 'alias', which allows the user to bind a new name to a command. * * @author ben - * */ public class GenericCommandMode implements CommandMode { - /* - * Contains the commands this mode handles - */ - private final IMap<String, Command> commandHandlers; - private final IMap<String, Command> defaultHandlers; + /* Contains the commands this mode handles. */ + private final IMap<String, Command> commandHandlers; + /* Commands to execute in every mode. */ + private final IMap<String, Command> defaultHandlers; - /* - * Contains help topics without an associated command - */ + /* Contains help topics without an associated command */ private final IMap<String, CommandHelp> helpTopics; - /* - * The action to execute upon encountering an unknown command - */ + /* The action to execute upon encountering an unknown command */ private BiConsumer<String, String[]> unknownCommandHandler; - /* - * The functions to use for input/output - */ - private final Consumer<String> errorOutput; - private final Consumer<String> normalOutput; + /* The functions to use for input/output */ + private final Consumer<String> errorOutput; + private final Consumer<String> normalOutput; - /* - * The name of this command mode, or null if it is unnamed - */ + /* The name of this command mode, or null if it is unnamed */ private String modeName; - /* - * The custom prompt to use, or null if none is specified - */ + /* The custom prompt to use, or null if none is specified */ private String customPrompt; /** * Create a new generic command mode * * @param normalOutput - * The function to use for normal output + * The function to use for normal output. + * * @param errorOutput - * The function to use for error output + * The function to use for error output. */ public GenericCommandMode(final Consumer<String> normalOutput, final Consumer<String> errorOutput) { - if (normalOutput == null) - throw new NullPointerException("Normal output source must be non-null"); + if (normalOutput == null) throw new NullPointerException("Normal output source must be non-null"); else if (errorOutput == null) throw new NullPointerException("Error output source must be non-null"); this.normalOutput = normalOutput; - this.errorOutput = errorOutput; + this.errorOutput = errorOutput; - /* - * Initialize handler maps so that they sort in alphabetical - */ - /* - * order - */ + /* Initialize maps so that they sort in alphabetical order. */ commandHandlers = new FunctionalMap<>(new TreeMap<>()); defaultHandlers = new FunctionalMap<>(new TreeMap<>()); - helpTopics = new FunctionalMap<>(new TreeMap<>()); + helpTopics = new FunctionalMap<>(new TreeMap<>()); + /* Setup default commands. */ setupDefaultCommands(); } /** - * Add an alias to an existing command + * Add an alias to an existing command. * * @param commandName - * The name of the command to add an alias for + * The name of the command to add an alias for. + * * @param aliasName - * The new alias for the command + * The new alias for the command. * * @throws IllegalArgumentException - * if the specified command doesn't have a bound - * handler, or if the alias name already has a bound - * value + * If the specified command doesn't have a bound handler, or if the + * alias name already has a bound value. */ public void addCommandAlias(final String commandName, final String aliasName) { - if (commandName == null) + if (commandName == null) { throw new NullPointerException("Command name must not be null"); - else if (aliasName == null) - throw new NullPointerException("Alias name must not be null"); - else if (!commandHandlers.containsKey(commandName) && !defaultHandlers.containsKey(commandName)) - throw new IllegalArgumentException("Cannot alias non-existant command '" + commandName + "'"); - else if (commandHandlers.containsKey(aliasName) || defaultHandlers.containsKey(aliasName)) - throw new IllegalArgumentException( - "Cannot bind alias '" + aliasName + "' to a command with a bound handler"); - else { + } else if (aliasName == null) { + String msg = "Alias name must not be null"; + throw new NullPointerException(msg); + } else if (!commandHandlers.containsKey(commandName) && !defaultHandlers.containsKey(commandName)) { + String msg = String.format("Cannot alias non-existant command '%s'", commandName); + throw new IllegalArgumentException(msg); + } else if (commandHandlers.containsKey(aliasName) || defaultHandlers.containsKey(aliasName)) { + String msg = String.format("Cannot bind alias '%s' to an already bound command.", aliasName); + throw new IllegalArgumentException(msg); + } else { + /* The command that will be aliased. */ Command aliasedCommand; + /* Get the alias. */ if (defaultHandlers.containsKey(commandName)) { aliasedCommand = defaultHandlers.get(commandName).aliased(); } else { @@ -116,45 +104,49 @@ public class GenericCommandMode implements CommandMode { } /** - * Add a command to this command mode + * Add a command to this command mode. * * @param command - * The name of the command to add + * The name of the command to add. + * * @param handler - * The handler to use for the specified command + * The handler to use for the specified command. * * @throws IllegalArgumentException - * if the specified command already has a handler - * registered + * If the specified command already has a handler registered. */ public void addCommandHandler(final String command, final Command handler) { - if (command == null) + if (command == null) { throw new NullPointerException("Command must not be null"); - else if (handler == null) + } else if (handler == null) { throw new NullPointerException("Handler must not be null"); - else if (canHandle(command)) - throw new IllegalArgumentException("Command " + command + " already has a handler registered"); - else { + } else if (canHandle(command)) { + String msg = String.format("Command '%s' already has a registered handler"); + throw new IllegalArgumentException(msg); + } else { commandHandlers.put(command, handler); } } /** - * Add a help topic to this command mode that isn't tied to a command + * Add a help topic to this command mode that isn't tied to a command. * * @param topicName - * The name of the topic + * The name of the topic. + * * @param topic - * The contents of the topic + * The contents of the topic. */ public void addHelpTopic(final String topicName, final CommandHelp topic) { helpTopics.put(topicName, topic); } + /* Default command builders */ /* - * Default command builders + * @TODO 10/09/17 Ben Culkin :CommandExtraction + * These command messages should be extracted into some kind of + * file-based abstraction. */ - private GenericCommand buildAliasCommand() { final String aliasShortHelp = "alias\tAlias one command to another"; final String aliasLongHelp = "Gives a command another name it can be invoked by." @@ -200,14 +192,10 @@ public class GenericCommandMode implements CommandMode { return new GenericCommand((args) -> { if (args == null || args.length == 0) { - /* - * Invoke general help - */ + /* Invoke general help */ doHelpSummary(); } else { - /* - * Invoke help for a command - */ + /* Invoke help for a command */ doHelpCommand(args[0]); } @@ -232,22 +220,23 @@ public class GenericCommandMode implements CommandMode { return commandHandlers.containsKey(command) || defaultHandlers.containsKey(command); } - /* - * Implement default commands - */ - + /* Implement default commands */ private void doAliasCommands(final String[] args) { if (args.length != 2) { - errorOutput.accept("ERROR: Alias requires two arguments." - + " The command name, and the alias for that command"); + String msg = String.format("ERROR: Alias requires two arguments. The command name, and the alias for that command. "); + errorOutput.accept(msg); } else { final String commandName = args[0]; final String aliasName = args[1]; if (!canHandle(commandName)) { - errorOutput.accept("ERROR: '" + commandName + "' is not a valid command."); + String msg = String.format("ERROR: '%s' is not a valid command.", commandName); + + errorOutput.accept(msg); } else if (canHandle(aliasName)) { - errorOutput.accept("ERROR: Cannot overwrite command '" + aliasName + "'"); + String msg = String.format("ERROR: Cannot overwrite command '%s'", aliasName); + + errorOutput.accept(msg); } else { addCommandAlias(commandName, aliasName); } @@ -266,8 +255,9 @@ public class GenericCommandMode implements CommandMode { } else if (helpTopics.containsKey(commandName)) { normalOutput.accept("\n" + helpTopics.get(commandName).getDescription()); } else { - errorOutput.accept( - "ERROR: I'm sorry, but there is no help available for '" + commandName + "'"); + String msg = String.format("ERROR: No help available for '%s'", commandName); + + errorOutput.accept(msg); } } @@ -277,7 +267,10 @@ public class GenericCommandMode implements CommandMode { if (commandHandlers.size() > 0) { commandHandlers.forEachValue(command -> { if (!command.isAlias()) { - normalOutput.accept("\t" + command.getHelp().getSummary() + "\n"); + String comLine = command.getHelp().getSummary(); + String msg = String.format("\t%s\n", comLine); + + normalOutput.accept(msg); } }); } else { @@ -286,9 +279,17 @@ public class GenericCommandMode implements CommandMode { normalOutput.accept("\nHelp topics available in all command modes are as follows\n"); if (defaultHandlers.size() > 0) { + /* + * @NOTE + * This block here should be abstracted out into a + * method. + */ defaultHandlers.forEachValue(command -> { if (!command.isAlias()) { - normalOutput.accept("\t" + command.getHelp().getSummary() + "\n"); + String comLine = command.getHelp().getSummary(); + String msg = String.format("\t%s\n", comLine); + + normalOutput.accept(msg); } }); } else { @@ -298,7 +299,9 @@ public class GenericCommandMode implements CommandMode { normalOutput.accept("\nHelp topics not associated with a command are as follows\n"); if (helpTopics.size() > 0) { helpTopics.forEachValue(topic -> { - normalOutput.accept("\t" + topic.getSummary() + "\n"); + String msg = String.format("\t%s\n", topic.getSummary()); + + normalOutput.accept(msg); }); } else { normalOutput.accept("\tNone available\n"); @@ -309,12 +312,16 @@ public class GenericCommandMode implements CommandMode { normalOutput.accept("The available commands for this mode are as follows:\n"); commandHandlers.keyList().forEach(commandName -> { - normalOutput.accept("\t" + commandName); + String msg = String.format("\t%s", commandName); + + normalOutput.accept(msg); }); normalOutput.accept("\nThe following commands are available in all modes:\n"); defaultHandlers.keyList().forEach(commandName -> { - normalOutput.accept("\t" + commandName); + String msg = String.format("\t%s", commandName); + + normalOutput.accept(msg); }); normalOutput.accept("\n"); @@ -349,13 +356,22 @@ public class GenericCommandMode implements CommandMode { return commandHandlers.get(command).getHandler().handle(args); else { if (args != null) { - errorOutput.accept("ERROR: Unrecognized command " + command + String.join(" ", args)); + String argString = String.join(", ", args); + String msg = String.format("ERROR: Unrecognized command %s (arguments %s)", + command, argString); + + errorOutput.accept(msg); } else { - errorOutput.accept("ERROR: Unrecognized command " + command); + String msg = String.format("ERROR: Unrecognized command %s", command); + + errorOutput.accept(msg); } - if (unknownCommandHandler == null) - throw new UnsupportedOperationException("Command " + command + " is invalid."); + if (unknownCommandHandler == null) { + String msg = String.format("Command %s is invalid", command); + + throw new UnsupportedOperationException(msg); + } unknownCommandHandler.accept(command, args); } @@ -367,8 +383,8 @@ public class GenericCommandMode implements CommandMode { * Set the custom prompt for this mode * * @param prompt - * The custom prompt for this mode, or null to disable - * the custom prompt + * The custom prompt for this mode, or null to disable the custom + * prompt */ public void setCustomPrompt(final String prompt) { customPrompt = prompt; @@ -378,8 +394,7 @@ public class GenericCommandMode implements CommandMode { * Set the name of this mode * * @param name - * The desired name of this mode, or null to use the - * default name + * The desired name of this mode, or null to use the default name */ public void setModeName(final String name) { modeName = name; @@ -389,8 +404,8 @@ public class GenericCommandMode implements CommandMode { * Set the handler to use for unknown commands * * @param handler - * The handler to use for unknown commands, or null to - * throw on unknown commands + * The handler to use for unknown commands, or null to throw on + * unknown commands */ public void setUnknownCommandHandler(final BiConsumer<String, String[]> handler) { if (handler == null) throw new NullPointerException("Handler must not be null"); @@ -398,25 +413,20 @@ public class GenericCommandMode implements CommandMode { unknownCommandHandler = handler; } + /* Setup default commands. */ private void setupDefaultCommands() { - defaultHandlers.put("list", buildListCommand()); + defaultHandlers.put("list", buildListCommand()); defaultHandlers.put("alias", buildAliasCommand()); - defaultHandlers.put("help", buildHelpCommand()); + defaultHandlers.put("help", buildHelpCommand()); + /* Help unix people :) */ addCommandAlias("help", "man"); + /* Add commands handled in a upper layer. */ /* - * Add commands handled in a upper layer. - */ - - /* - * @TODO figure out a place to put commands that apply across - */ - /* - * all - */ - /* - * modes, but only apply to a specific application + * @NOTE + * Figure out a place to put commands that apply across all + * modes, but only to a specific application. */ defaultHandlers.put("clear", buildClearCommands()); defaultHandlers.put("exit", buildExitCommand()); @@ -465,5 +475,4 @@ public class GenericCommandMode implements CommandMode { return builder.toString(); } - } diff --git a/base/src/main/java/bjc/utils/cli/GenericHelp.java b/base/src/main/java/bjc/utils/cli/GenericHelp.java index 38adf57..92c1eef 100644 --- a/base/src/main/java/bjc/utils/cli/GenericHelp.java +++ b/base/src/main/java/bjc/utils/cli/GenericHelp.java @@ -1,35 +1,39 @@ package bjc.utils.cli; /** - * Generic implementation of a help topic + * Generic implementation of a help topic. * * @author ben - * */ public class GenericHelp implements CommandHelp { - // The strings for this help topic + /* The strings for this help topic. */ private final String summary; private final String description; /** - * Create a new help topic + * Create a new help topic. * * @param summary - * The summary of this help topic + * The summary of this help topic. + * * @param description - * The description of this help topic, or null if this - * help topic doesn't have a more detailed description + * The description of this help topic, or null if this help topic + * doesn't have a more detailed description. */ public GenericHelp(final String summary, final String description) { - if (summary == null) throw new NullPointerException("Help summary must be non-null"); + if (summary == null) { + throw new NullPointerException("Help summary must be non-null"); + } - this.summary = summary; + this.summary = summary; this.description = description; } @Override public String getDescription() { - if (description == null) return summary; + if (description == null) { + return summary; + } return description; } diff --git a/base/src/main/java/bjc/utils/cli/NullHelp.java b/base/src/main/java/bjc/utils/cli/NullHelp.java index 6c49ae6..5e5fb67 100644 --- a/base/src/main/java/bjc/utils/cli/NullHelp.java +++ b/base/src/main/java/bjc/utils/cli/NullHelp.java @@ -1,10 +1,9 @@ package bjc.utils.cli; /** - * Implementation of a help topic that doesn't exist + * Implementation of a help topic that doesn't exist. * * @author ben - * */ public class NullHelp implements CommandHelp { @Override diff --git a/base/src/main/java/bjc/utils/cli/objects/BlockReaderCLI.java b/base/src/main/java/bjc/utils/cli/objects/BlockReaderCLI.java index ec66fe2..2edea08 100644 --- a/base/src/main/java/bjc/utils/cli/objects/BlockReaderCLI.java +++ b/base/src/main/java/bjc/utils/cli/objects/BlockReaderCLI.java @@ -18,19 +18,46 @@ import bjc.utils.ioutils.blocks.*; import static bjc.utils.cli.objects.Command.CommandStatus; import static bjc.utils.cli.objects.Command.CommandStatus.*; +/** + * Command-line interface for configuring block readers. + * + * @author Ben Culkin + */ public class BlockReaderCLI { + /* Logger. */ private final Logger LOGGER = Logger.getLogger(BlockReaderCLI.class.getName()); + /** + * The state of the block reader. + * + * @author Ben Culkin + */ public static class BlockReaderState { + /** + * All of the configured block readers. + */ public final Map<String, BlockReader> readers; + /** + * All of the configured I/O sources. + */ public final Map<String, Reader> sources; + /** + * Create a new set of state for the block reader. + * + * @param readers + * The set of configured block readers. + * + * @param sources + * The set of configured I/O sources. + */ public BlockReaderState(Map<String, BlockReader> readers, Map<String, Reader> sources) { this.readers = readers; this.sources = sources; } } + /* Our state. */ private BlockReaderState stat; /** @@ -43,16 +70,33 @@ public class BlockReaderCLI { stat = new BlockReaderState(new HashMap<>(), srcs); } + /** + * Create a new CLI for configuring BlockReaders. + * + * @param state + * The state object to use. + */ + public BlockReaderCLI(BlockReaderState state) { + stat = state; + } + + /* :CLIArgsParsing */ + /** + * Run the command line interface + * + * @param args + * Ignored CLI args. + */ public static void main(String[] args) { - /* - * Create/configure I/O sources. - */ + /* Create/configure I/O sources. */ Map<String, Reader> sources = new HashMap<>(); - sources.put("stdio", new InputStreamReader(System.in)); + BlockReaderCLI reader = new BlockReaderCLI(sources); - BlockReaderCLI reader = new BlockReaderCLI(sources); + sources.put("stdio", new InputStreamReader(System.in)); - reader.run(new Scanner(System.in), "console", true); + Scanner input = new Scanner(System.in); + reader.run(input, "console", true); + input.close(); } /** @@ -60,61 +104,79 @@ public class BlockReaderCLI { * * @param input * The place to read input from. + * * @param ioSource * The name of the place to read input from. + * * @param interactive * Whether or not the source is interactive */ public void run(Scanner input, String ioSource, boolean interactive) { int lno = 0; - while(input.hasNextLine()) { - if(interactive) - System.out.printf("reader-conf(%d)>", lno); + /* Print a prompt. */ + if(interactive) { + System.out.printf("reader-conf(%d)>", lno); + } + while(input.hasNextLine()) { + /* Read a line. */ String ln = input.nextLine(); - lno += 1; + /* Parse the command. */ Command com = Command.fromString(ln, lno, ioSource); + /* Ignore blank commands. */ if(com == null) continue; + /* Handle a command. */ CommandStatus stat = handleCommand(com, interactive); + /* Exit if we finished or encountered a fatal error. */ if(stat == FINISH || stat == ERROR) { return; } - } - input.close(); + /* Print a prompt. */ + if(interactive) { + System.out.printf("reader-conf(%d)>", lno); + } + + } } - /* + /** * Handle a command. + * + * @param com + * The command to handle + * + * @param interactive + * Whether the current input source is interactive or not. */ public CommandStatus handleCommand(Command com, boolean interactive) { switch(com.nameCommand) { - case "def-filtered": - return defFiltered(com); - case "def-layered": - return defLayered(com); - case "def-pushback": - return defPushback(com); - case "def-simple": - return defSimple(com); - case "def-serial": - return defSerial(com); - case "def-toggled": - return defToggled(com); - case "}": - case "end": - case "exit": - case "quit": - if(interactive) - System.out.printf("Exiting reader-conf, %d readers configured in %d commands\n", - stat.readers.size(), com.lineNo); - return FINISH; - default: - LOGGER.severe(com.error("Unknown command '%s'\n", com.nameCommand)); - return FAIL; + case "def-filtered": + return defFiltered(com); + case "def-layered": + return defLayered(com); + case "def-pushback": + return defPushback(com); + case "def-simple": + return defSimple(com); + case "def-serial": + return defSerial(com); + case "def-toggled": + return defToggled(com); + case "}": + case "end": + case "exit": + case "quit": + if(interactive) + System.out.printf("Exiting reader-conf, %d readers configured in %d commands\n", + stat.readers.size(), com.lineNo); + return FINISH; + default: + LOGGER.severe(com.error("Unknown command '%s'\n", com.nameCommand)); + return FAIL; } } diff --git a/base/src/main/java/bjc/utils/cli/objects/Command.java b/base/src/main/java/bjc/utils/cli/objects/Command.java index e605a2b..3a7d452 100644 --- a/base/src/main/java/bjc/utils/cli/objects/Command.java +++ b/base/src/main/java/bjc/utils/cli/objects/Command.java @@ -1,8 +1,15 @@ package bjc.utils.cli.objects; +/** + * A single-line command read from the user. + * + * @author Ben Culkin + */ public class Command { /** * Command status values. + * + * @author Ben Culkin */ public static enum CommandStatus { /** @@ -23,21 +30,38 @@ public class Command { FINISH, } + /** + * The line number of this command. + */ public final int lineNo; + /** + * The full text of this command. + */ public final String fullCommand; + /** + * The text of this command without its name. + */ public final String remnCommand; + /** + * The name of this command. + */ public final String nameCommand; + /** + * The name of the I/O source this command was read from. + */ public final String ioSource; /** * Create a new command. * * @param ln - * The line to get the command from. + * The string to get the command from. + * * @param lno * The number of the line the command came from. + * * @param ioSrc * The name of where the I/O came from. */ @@ -55,16 +79,28 @@ public class Command { ioSource = ioSrc; } + /** + * Parse a command from a string. + * + * The main thing this does is ignore blank lines, as well as comments + * marked by #'s either at the start of the line or part of the way + * through the line. + * + * @param ln + * The string to get the command from. + * + * @param lno + * The line number of the command. + * + * @param ioSource + * The name of where the I/O came from. + */ public static Command fromString(String ln, int lno, String ioSource) { - /* - * Ignore blank lines and comments. - */ + /* Ignore blank lines and comments. */ if(ln.equals("")) return null; if(ln.startsWith("#")) return null; - /* - * Trim off comments part-way through the line. - */ + /* Trim off comments part-way through the line. */ int idxHash = ln.indexOf('#'); if(idxHash != -1) { ln = ln.substring(0, idxHash).trim(); @@ -73,12 +109,46 @@ public class Command { return new Command(ln, lno, ioSource); } + /** + * Give an informational message about something in relation to this + * command. + * + * @param info + * The informational message. + * + * @param parms + * The parameters for the informational message. + */ + public String info(String info, Object... parms) { + String msg = String.format(info, parms); + + return String.format("INFO (%s:%d): %s", ioSource, lineNo, msg); + } + + /** + * Warn about something in relation to this command. + * + * @param warning + * The warning message. + * + * @param parms + * The parameters for the warning message. + */ public String warn(String warning, Object... parms) { String msg = String.format(warning, parms); return String.format("WARNING (%s:%d): %s", ioSource, lineNo, msg); } + /** + * Give an error about something in relation to this command. + * + * @param error + * The error message. + * + * @param parms + * The parameters for the error message. + */ public String error(String err, Object... parms) { String msg = String.format(err, parms); diff --git a/base/src/main/java/bjc/utils/cli/objects/DefineCLI.java b/base/src/main/java/bjc/utils/cli/objects/DefineCLI.java index bb2733f..5763a83 100644 --- a/base/src/main/java/bjc/utils/cli/objects/DefineCLI.java +++ b/base/src/main/java/bjc/utils/cli/objects/DefineCLI.java @@ -10,6 +10,16 @@ import java.util.regex.Pattern; import static bjc.utils.cli.objects.Command.CommandStatus; import static bjc.utils.cli.objects.Command.CommandStatus.*; +/* + * @TODO 10/09/17 :DefineCLIFinish + * This got left off about halfway through due to getting distracted + * implementing CL-style format strings. It needs to be finished. + */ +/** + * Command-line interface for building defines. + * + * @author Ben Culkin + */ public class DefineCLI { private final Logger LOGGER = Logger.getLogger(DefineCLI.class.getName()); |
