summaryrefslogtreecommitdiff
path: root/BJC-Utils2/src/main/java/bjc/utils/cli
diff options
context:
space:
mode:
Diffstat (limited to 'BJC-Utils2/src/main/java/bjc/utils/cli')
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/cli/CLICommander.java6
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/cli/Command.java (renamed from BJC-Utils2/src/main/java/bjc/utils/cli/ICommand.java)10
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/cli/CommandHandler.java (renamed from BJC-Utils2/src/main/java/bjc/utils/cli/ICommandHandler.java)4
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/cli/CommandHelp.java (renamed from BJC-Utils2/src/main/java/bjc/utils/cli/ICommandHelp.java)2
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/cli/CommandMode.java (renamed from BJC-Utils2/src/main/java/bjc/utils/cli/ICommandMode.java)6
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/cli/DelegatingCommand.java12
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/cli/GenericCommand.java14
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/cli/GenericCommandMode.java26
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/cli/GenericHelp.java2
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/cli/NullHelp.java2
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/cli/fds/FDS.java69
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/cli/fds/FDSCommand.java26
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/cli/fds/FDSException.java32
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/cli/fds/FDSMode.java94
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/cli/fds/SimpleFDSMode.java142
15 files changed, 405 insertions, 42 deletions
diff --git a/BJC-Utils2/src/main/java/bjc/utils/cli/CLICommander.java b/BJC-Utils2/src/main/java/bjc/utils/cli/CLICommander.java
index 719d6ca..56a4be0 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/cli/CLICommander.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/cli/CLICommander.java
@@ -23,7 +23,7 @@ public class CLICommander {
/*
* The command mode to start execution in.
*/
- private ICommandMode initialMode;
+ private CommandMode initialMode;
/**
* Create a new CLI interface powered by streams.
@@ -69,7 +69,7 @@ public class CLICommander {
*
* Used to preserve the initial mode.
*/
- ICommandMode currentMode = initialMode;
+ CommandMode currentMode = initialMode;
/*
* Process commands until we're told to stop.
@@ -124,7 +124,7 @@ public class CLICommander {
* @param initialMode
* The initial command mode to use.
*/
- public void setInitialCommandMode(ICommandMode initialMode) {
+ public void setInitialCommandMode(CommandMode initialMode) {
if(initialMode == null) throw new NullPointerException("Initial mode must be non-zero");
this.initialMode = initialMode;
diff --git a/BJC-Utils2/src/main/java/bjc/utils/cli/ICommand.java b/BJC-Utils2/src/main/java/bjc/utils/cli/Command.java
index 6d30c6a..02bc061 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/cli/ICommand.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/cli/Command.java
@@ -1,32 +1,32 @@
package bjc.utils.cli;
/**
- * Represents a command that can be invoked from a {@link ICommandMode}
+ * Represents a command that can be invoked from a {@link CommandMode}
*
* @author ben
*
*/
-public interface ICommand {
+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
*/
- ICommand aliased();
+ Command aliased();
/**
* Get the handler that executes this command
*
* @return The handler that executes this command
*/
- ICommandHandler getHandler();
+ CommandHandler getHandler();
/**
* Get the help entry for this command
*
* @return The help entry for this command
*/
- ICommandHelp getHelp();
+ CommandHelp getHelp();
/**
* Check if this command is an alias of another command
diff --git a/BJC-Utils2/src/main/java/bjc/utils/cli/ICommandHandler.java b/BJC-Utils2/src/main/java/bjc/utils/cli/CommandHandler.java
index d1f7f77..0a3534f 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/cli/ICommandHandler.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/cli/CommandHandler.java
@@ -9,7 +9,7 @@ import java.util.function.Function;
*
*/
@FunctionalInterface
-public interface ICommandHandler extends Function<String[], ICommandMode> {
+public interface CommandHandler extends Function<String[], CommandMode> {
/**
* Execute this command
*
@@ -18,7 +18,7 @@ public interface ICommandHandler extends Function<String[], ICommandMode> {
* @return The command mode to switch to after this command, or null to
* stop executing commands
*/
- default ICommandMode handle(String[] args) {
+ default CommandMode handle(String[] args) {
return this.apply(args);
}
}
diff --git a/BJC-Utils2/src/main/java/bjc/utils/cli/ICommandHelp.java b/BJC-Utils2/src/main/java/bjc/utils/cli/CommandHelp.java
index f267594..327fb75 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/cli/ICommandHelp.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/cli/CommandHelp.java
@@ -6,7 +6,7 @@ package bjc.utils.cli;
* @author ben
*
*/
-public interface ICommandHelp {
+public interface CommandHelp {
/**
* Get the description of a command.
*
diff --git a/BJC-Utils2/src/main/java/bjc/utils/cli/ICommandMode.java b/BJC-Utils2/src/main/java/bjc/utils/cli/CommandMode.java
index 431a8cf..d26b176 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/cli/ICommandMode.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/cli/CommandMode.java
@@ -7,7 +7,7 @@ package bjc.utils.cli;
* @author ben
*
*/
-public interface ICommandMode extends Comparable<ICommandMode> {
+public interface CommandMode extends Comparable<CommandMode> {
/**
* Check to see if this mode can handle the specified command
*
@@ -61,12 +61,12 @@ public interface ICommandMode extends Comparable<ICommandMode> {
* @return The command mode to use for the next command. Defaults to
* returning this, and doing nothing else
*/
- default ICommandMode process(String command, String[] args) {
+ default CommandMode process(String command, String[] args) {
return this;
}
@Override
- default int compareTo(ICommandMode o) {
+ default int compareTo(CommandMode o) {
return getName().compareTo(o.getName());
}
}
diff --git a/BJC-Utils2/src/main/java/bjc/utils/cli/DelegatingCommand.java b/BJC-Utils2/src/main/java/bjc/utils/cli/DelegatingCommand.java
index 99d7e43..dbbb047 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/cli/DelegatingCommand.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/cli/DelegatingCommand.java
@@ -6,11 +6,11 @@ package bjc.utils.cli;
* @author ben
*
*/
-class DelegatingCommand implements ICommand {
+class DelegatingCommand implements Command {
/*
* The command to delegate to.
*/
- private ICommand delegate;
+ private Command delegate;
/**
* Create a new command that delegates to another command.
@@ -18,22 +18,22 @@ class DelegatingCommand implements ICommand {
* @param delegate
* The command to delegate to.
*/
- public DelegatingCommand(ICommand delegate) {
+ public DelegatingCommand(Command delegate) {
this.delegate = delegate;
}
@Override
- public ICommand aliased() {
+ public Command aliased() {
return new DelegatingCommand(delegate);
}
@Override
- public ICommandHandler getHandler() {
+ public CommandHandler getHandler() {
return delegate.getHandler();
}
@Override
- public ICommandHelp getHelp() {
+ public CommandHelp getHelp() {
return delegate.getHelp();
}
diff --git a/BJC-Utils2/src/main/java/bjc/utils/cli/GenericCommand.java b/BJC-Utils2/src/main/java/bjc/utils/cli/GenericCommand.java
index ea10108..c49b4b9 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/cli/GenericCommand.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/cli/GenericCommand.java
@@ -6,16 +6,16 @@ package bjc.utils.cli;
* @author ben
*
*/
-public class GenericCommand implements ICommand {
+public class GenericCommand implements Command {
/*
* The behavior for invoking the command.
*/
- private ICommandHandler handler;
+ private CommandHandler handler;
/*
* The help for the command.
*/
- private ICommandHelp help;
+ private CommandHelp help;
/**
* Create a new generic command.
@@ -30,7 +30,7 @@ public class GenericCommand implements ICommand {
* null, in which case the description is repeated for
* the detailed help.
*/
- public GenericCommand(ICommandHandler handler, String description, String help) {
+ public GenericCommand(CommandHandler handler, String description, String help) {
if(handler == null) throw new NullPointerException("Command handler must not be null");
this.handler = handler;
@@ -43,17 +43,17 @@ public class GenericCommand implements ICommand {
}
@Override
- public ICommand aliased() {
+ public Command aliased() {
return new DelegatingCommand(this);
}
@Override
- public ICommandHandler getHandler() {
+ public CommandHandler getHandler() {
return handler;
}
@Override
- public ICommandHelp getHelp() {
+ public CommandHelp getHelp() {
return help;
}
diff --git a/BJC-Utils2/src/main/java/bjc/utils/cli/GenericCommandMode.java b/BJC-Utils2/src/main/java/bjc/utils/cli/GenericCommandMode.java
index ee2bdbb..7977391 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/cli/GenericCommandMode.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/cli/GenericCommandMode.java
@@ -17,17 +17,17 @@ import java.util.function.Consumer;
* @author ben
*
*/
-public class GenericCommandMode implements ICommandMode {
+public class GenericCommandMode implements CommandMode {
/*
* Contains the commands this mode handles
*/
- private IMap<String, ICommand> commandHandlers;
- private IMap<String, ICommand> defaultHandlers;
+ private IMap<String, Command> commandHandlers;
+ private IMap<String, Command> defaultHandlers;
/*
* Contains help topics without an associated command
*/
- private IMap<String, ICommandHelp> helpTopics;
+ private IMap<String, CommandHelp> helpTopics;
/*
* The action to execute upon encountering an unknown command
@@ -103,7 +103,7 @@ public class GenericCommandMode implements ICommandMode {
throw new IllegalArgumentException(
"Cannot bind alias '" + aliasName + "' to a command with a bound handler");
else {
- ICommand aliasedCommand;
+ Command aliasedCommand;
if(defaultHandlers.containsKey(commandName)) {
aliasedCommand = defaultHandlers.get(commandName).aliased();
@@ -127,7 +127,7 @@ public class GenericCommandMode implements ICommandMode {
* if the specified command already has a handler
* registered
*/
- public void addCommandHandler(String command, ICommand handler) {
+ public void addCommandHandler(String command, Command handler) {
if(command == null)
throw new NullPointerException("Command must not be null");
else if(handler == null)
@@ -147,7 +147,7 @@ public class GenericCommandMode implements ICommandMode {
* @param topic
* The contents of the topic
*/
- public void addHelpTopic(String topicName, ICommandHelp topic) {
+ public void addHelpTopic(String topicName, CommandHelp topic) {
helpTopics.put(topicName, topic);
}
@@ -274,7 +274,7 @@ public class GenericCommandMode implements ICommandMode {
private void doHelpSummary() {
normalOutput.accept("Help topics for this command mode are as follows:\n");
- if(commandHandlers.getSize() > 0) {
+ if(commandHandlers.size() > 0) {
commandHandlers.forEachValue(command -> {
if(!command.isAlias()) {
normalOutput.accept("\t" + command.getHelp().getSummary() + "\n");
@@ -285,7 +285,7 @@ public class GenericCommandMode implements ICommandMode {
}
normalOutput.accept("\nHelp topics available in all command modes are as follows\n");
- if(defaultHandlers.getSize() > 0) {
+ if(defaultHandlers.size() > 0) {
defaultHandlers.forEachValue(command -> {
if(!command.isAlias()) {
normalOutput.accept("\t" + command.getHelp().getSummary() + "\n");
@@ -296,7 +296,7 @@ public class GenericCommandMode implements ICommandMode {
}
normalOutput.accept("\nHelp topics not associated with a command are as follows\n");
- if(helpTopics.getSize() > 0) {
+ if(helpTopics.size() > 0) {
helpTopics.forEachValue(topic -> {
normalOutput.accept("\t" + topic.getSummary() + "\n");
});
@@ -324,14 +324,14 @@ public class GenericCommandMode implements ICommandMode {
public String getCustomPrompt() {
if(customPrompt != null) return customPrompt;
- return ICommandMode.super.getCustomPrompt();
+ return CommandMode.super.getCustomPrompt();
}
@Override
public String getName() {
if(modeName != null) return modeName;
- return ICommandMode.super.getName();
+ return CommandMode.super.getName();
}
@Override
@@ -340,7 +340,7 @@ public class GenericCommandMode implements ICommandMode {
}
@Override
- public ICommandMode process(String command, String[] args) {
+ public CommandMode process(String command, String[] args) {
normalOutput.accept("\n");
if(defaultHandlers.containsKey(command))
diff --git a/BJC-Utils2/src/main/java/bjc/utils/cli/GenericHelp.java b/BJC-Utils2/src/main/java/bjc/utils/cli/GenericHelp.java
index bbdd1fc..edda5c0 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/cli/GenericHelp.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/cli/GenericHelp.java
@@ -6,7 +6,7 @@ package bjc.utils.cli;
* @author ben
*
*/
-public class GenericHelp implements ICommandHelp {
+public class GenericHelp implements CommandHelp {
// The strings for this help topic
private String summary;
private String description;
diff --git a/BJC-Utils2/src/main/java/bjc/utils/cli/NullHelp.java b/BJC-Utils2/src/main/java/bjc/utils/cli/NullHelp.java
index 0d511a4..289d9c1 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/cli/NullHelp.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/cli/NullHelp.java
@@ -6,7 +6,7 @@ package bjc.utils.cli;
* @author ben
*
*/
-public class NullHelp implements ICommandHelp {
+public class NullHelp implements CommandHelp {
@Override
public String getDescription() {
return "No description provided";
diff --git a/BJC-Utils2/src/main/java/bjc/utils/cli/fds/FDS.java b/BJC-Utils2/src/main/java/bjc/utils/cli/fds/FDS.java
new file mode 100644
index 0000000..6dc0337
--- /dev/null
+++ b/BJC-Utils2/src/main/java/bjc/utils/cli/fds/FDS.java
@@ -0,0 +1,69 @@
+package bjc.utils.cli.fds;
+
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.PrintStream;
+import bjc.utils.ioutils.Block;
+import bjc.utils.ioutils.BlockReader;
+
+/**
+ * Runs a FDS (FDiskScript) interface.
+ *
+ * This is a rudimentary console interface inspired heavily by FDisk's interface
+ * style.
+ *
+ * Commands are denoted by a single character, but can invoke submodes.
+ *
+ * @author bjculkin
+ *
+ */
+public class FDS {
+ /**
+ * Run a provided FDS mode until it is exited or there is no more input.
+ *
+ * @param comin
+ * The command input source for the FDS mode.
+ *
+ * @param datain
+ * The data input source for the FDS mode.
+ *
+ * @param out
+ * The output source for the FDS mode.
+ *
+ * @param initialMode
+ * The mode to start in.
+ *
+ * @param initialState
+ * The initial state for the mode.
+ *
+ * @return The final state of the mode.
+ *
+ * @throws FDSException
+ * If something went wrong during mode execution.
+ */
+ public static <S> S runFDS(InputStream comin, InputStream datain, OutputStream out, FDSMode<S> initialMode,
+ S initialState) throws FDSException {
+ PrintStream printer = new PrintStream(out);
+
+ try (BlockReader blockSource = new BlockReader("\\R", new InputStreamReader(comin))) {
+ printer.print("Enter a command (m for help): ");
+
+ while (blockSource.hasNext()) {
+ Block comBlock = blockSource.next();
+
+ String comString = comBlock.contents.trim();
+
+ char comChar = comString.charAt(0);
+
+ printer.println(String.format("\nRecieved command '%s'\n", comChar));
+
+ printer.print("Enter a command (m for help): ");
+ }
+ } catch (Exception ex) {
+ throw new FDSException("Unexpected I/O error", ex);
+ }
+
+ return initialState;
+ }
+}
diff --git a/BJC-Utils2/src/main/java/bjc/utils/cli/fds/FDSCommand.java b/BJC-Utils2/src/main/java/bjc/utils/cli/fds/FDSCommand.java
new file mode 100644
index 0000000..0a6d29c
--- /dev/null
+++ b/BJC-Utils2/src/main/java/bjc/utils/cli/fds/FDSCommand.java
@@ -0,0 +1,26 @@
+package bjc.utils.cli.fds;
+
+import java.util.Iterator;
+
+/**
+ * A command attached to an FDS interface.
+ *
+ * @author bjculkin
+ *
+ * @param <S>
+ * The state type of the interface.
+ */
+public interface FDSCommand<S> {
+ /**
+ * Run this command.
+ *
+ * @param state
+ * The current FDS state.
+ *
+ * @param input
+ * The source for data input.
+ *
+ * @return The new state, after running the command.
+ */
+ S run(S state, Iterator<String> input);
+}
diff --git a/BJC-Utils2/src/main/java/bjc/utils/cli/fds/FDSException.java b/BJC-Utils2/src/main/java/bjc/utils/cli/fds/FDSException.java
new file mode 100644
index 0000000..7569d95
--- /dev/null
+++ b/BJC-Utils2/src/main/java/bjc/utils/cli/fds/FDSException.java
@@ -0,0 +1,32 @@
+package bjc.utils.cli.fds;
+
+/**
+ * Exception thrown when something goes wrong with FDS.
+ *
+ * @author bjculkin
+ *
+ */
+public class FDSException extends Exception {
+ /**
+ * Create a new FDS exception with a message and a cause.
+ *
+ * @param message
+ * The message for the exception.
+ *
+ * @param cause
+ * The cause of the exception.
+ */
+ public FDSException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ /**
+ * Create a new FDS exception with a message.
+ *
+ * @param message
+ * The message for the exception.
+ */
+ public FDSException(String message) {
+ super(message);
+ }
+}
diff --git a/BJC-Utils2/src/main/java/bjc/utils/cli/fds/FDSMode.java b/BJC-Utils2/src/main/java/bjc/utils/cli/fds/FDSMode.java
new file mode 100644
index 0000000..acdcbcb
--- /dev/null
+++ b/BJC-Utils2/src/main/java/bjc/utils/cli/fds/FDSMode.java
@@ -0,0 +1,94 @@
+package bjc.utils.cli.fds;
+
+import bjc.utils.cli.CommandHelp;
+import bjc.utils.cli.NullHelp;
+
+/**
+ * A collection of related FDS commands.
+ *
+ * @author bjculkin
+ *
+ * @param <S>
+ * The FDS state type.
+ */
+public interface FDSMode<S> {
+ /**
+ * Get all the characters that are registered to something in this mode.
+ *
+ * In this context, something means a command or submode.
+ *
+ * @return All of the characters registered to something in this mode.
+ */
+ char[] registeredChars();
+
+ /*
+ * Check for the existence of commands/submodes.
+ */
+
+ /**
+ * Check if there is a command registered to the given character.
+ *
+ * @param c
+ * The character to check
+ *
+ * @return Whether or not there is a command bound to that character.
+ */
+ boolean hasCommand(char c);
+
+ /**
+ * Check if there is a submode registered to the given character.
+ *
+ * @param c
+ * The character to check
+ *
+ * @return Whether or not there is a submode bound to that character.
+ */
+ boolean hasSubmode(char c);
+
+ /*
+ * Get commands and submodes.
+ */
+
+ /**
+ * Get the command attached to a given character.
+ *
+ * @param c
+ * The character to get the command for.
+ *
+ * @return The command bound to that character.
+ *
+ * @throws FDSException
+ * If there is no command bound to that character.
+ */
+ FDSCommand<S> getCommand(char c) throws FDSException;
+
+ /**
+ * Get the command attached to a given character.
+ *
+ * @param c
+ * The character to get the command for.
+ *
+ * @return The command bound to that character.
+ *
+ * @throws FDSException
+ * If there is no command bound to that character.
+ */
+ FDSMode<S> getSubmode(char c) throws FDSException;
+
+ /*
+ * Help utilities
+ */
+ /**
+ * Get the help for what's bound to a character.
+ *
+ * This should be one line.
+ *
+ * @param c
+ * The character to look at the help for.
+ *
+ * @return The help for what's bound to the character.
+ */
+ default CommandHelp getHelp(char c) {
+ return new NullHelp();
+ }
+}
diff --git a/BJC-Utils2/src/main/java/bjc/utils/cli/fds/SimpleFDSMode.java b/BJC-Utils2/src/main/java/bjc/utils/cli/fds/SimpleFDSMode.java
new file mode 100644
index 0000000..2f6e660
--- /dev/null
+++ b/BJC-Utils2/src/main/java/bjc/utils/cli/fds/SimpleFDSMode.java
@@ -0,0 +1,142 @@
+package bjc.utils.cli.fds;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import bjc.utils.cli.CommandHelp;
+
+import static java.lang.String.format;
+
+/**
+ * Simple implementation of {@link FDSMode}.
+ *
+ * @author bjculkin
+ *
+ * @param <S>
+ * The FDS state type.
+ */
+public class SimpleFDSMode<S> implements FDSMode<S> {
+ private Map<Character, FDSCommand<S>> commands;
+ private Map<Character, FDSMode<S>> modes;
+ private Map<Character, CommandHelp> help;
+
+ private Set<Character> registered;
+ private char[] registeredArray;
+ private boolean changed;
+
+ /**
+ * Create a new empty FDS mode.
+ */
+ public SimpleFDSMode() {
+ commands = new HashMap<>();
+ modes = new HashMap<>();
+ help = new HashMap<>();
+
+ registered = new HashSet<>();
+ changed = true;
+ }
+
+ /**
+ * Add a command to the mode.
+ *
+ * @param c
+ * The character to bind to the command.
+ *
+ * @param comm
+ * The command to add.
+ *
+ * @param hlp
+ * The help for the command.
+ *
+ * @throws FDSException
+ * If the character is already bound to a command.
+ */
+ public void addCommand(char c, FDSCommand<S> comm, CommandHelp hlp) throws FDSException {
+ if (comm == null)
+ throw new NullPointerException("Command must not be null");
+ else if (commands.containsKey(c) || modes.containsKey(c))
+ throw new FDSException(format("Character '%s' is already bound"));
+
+ commands.put(c, comm);
+
+ registered.add(c);
+ if (!changed) changed = true;
+ }
+
+ /**
+ * Add a submode to the mode.
+ *
+ * @param c
+ * The character to bind to the submode.
+ *
+ * @param mode
+ * The submode to add.
+ *
+ * @throws FDSException
+ * If the character is already bound to a submode.
+ */
+ public void addSubmode(char c, FDSMode<S> mode) throws FDSException {
+ if (mode == null)
+ throw new NullPointerException("Mode must not be null");
+ else if (modes.containsKey(c) || commands.containsKey(c))
+ throw new FDSException(format("Character '%s' is already bound"));
+
+ modes.put(c, mode);
+
+ registered.add(c);
+ if (!changed) changed = true;
+ }
+
+ @Override
+ public char[] registeredChars() {
+ if (!changed) return registeredArray;
+
+ registeredArray = new char[registered.size()];
+
+ int i = 0;
+ for (char c : registered) {
+ registeredArray[i] = c;
+
+ i += 1;
+ }
+
+ changed = false;
+
+ return registeredArray;
+ }
+
+ @Override
+ public boolean hasCommand(char c) {
+ return commands.containsKey(c);
+ }
+
+ @Override
+ public boolean hasSubmode(char c) {
+ return modes.containsKey(c);
+ }
+
+ @Override
+ public FDSCommand<S> getCommand(char c) throws FDSException {
+ if (!commands.containsKey(c)) {
+ throw new FDSException(String.format("No command bound to '%s'", c));
+ }
+
+ return commands.get(c);
+ }
+
+ @Override
+ public FDSMode<S> getSubmode(char c) throws FDSException {
+ if (!modes.containsKey(c)) {
+ throw new FDSException(String.format("No mode bound to '%s'", c));
+ }
+
+ return modes.get(c);
+ }
+
+ @Override
+ public CommandHelp getHelp(char c) {
+ return help.get(c);
+ }
+} \ No newline at end of file