summaryrefslogtreecommitdiff
path: root/base/src/main/java/bjc/utils/cli
diff options
context:
space:
mode:
Diffstat (limited to 'base/src/main/java/bjc/utils/cli')
-rw-r--r--base/src/main/java/bjc/utils/cli/CLICommander.java76
-rw-r--r--base/src/main/java/bjc/utils/cli/Command.java13
-rw-r--r--base/src/main/java/bjc/utils/cli/CommandHandler.java13
-rw-r--r--base/src/main/java/bjc/utils/cli/CommandHelp.java9
-rw-r--r--base/src/main/java/bjc/utils/cli/CommandMode.java47
-rw-r--r--base/src/main/java/bjc/utils/cli/DelegatingCommand.java17
-rw-r--r--base/src/main/java/bjc/utils/cli/GenericCommand.java23
-rw-r--r--base/src/main/java/bjc/utils/cli/GenericCommandMode.java233
-rw-r--r--base/src/main/java/bjc/utils/cli/GenericHelp.java24
-rw-r--r--base/src/main/java/bjc/utils/cli/NullHelp.java3
-rw-r--r--base/src/main/java/bjc/utils/cli/objects/BlockReaderCLI.java134
-rw-r--r--base/src/main/java/bjc/utils/cli/objects/Command.java84
-rw-r--r--base/src/main/java/bjc/utils/cli/objects/DefineCLI.java10
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>
- * "&lt;command-name>\t&lt;command-summary>"
+ * "&lt;command-name&rt;\t&lt;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());