Why implement a command interface to a graphical debugger, you ask? That's easy, because it takes a lot less time to write a text parser than it does to put together a good looking graphical interface. I realized soon after starting this project that the coding needed to bring this graphical debugger from idea to reality was going to take a long time and a lot of effort. In the meantime I still would not have a satisfactory debugger. So, I have taken a sidetrack and implemented a command interface to this debugger, in addition to the graphical interface.
The command interface described here is not to be confused with the console mode of JSwat. The command interface is available in both the console and graphical modes of JSwat.
The basic design of the command interface is simple. There is a
means of receiving commands from the user and a class that
interprets them. This interpreter is the
CommandManager
class. This class is responsible for
parsing the text commands and taking the appropriate action. Since
one of my many goals for this project is extensibility and
flexibility, I have taken a simple approach to implementing the
commands. Each command is actually handled by a specialized class.
All command classes subclass from JSwatCommand
, which
provides some basic functionality for all commands. The
CommandManager
calls upon the command classes by their
name. For instance, the "suspend" command is implemented
by the suspendCommand
class. Thus the
CommandManager
has an easy time finding the command
class to handle the user's input.
Each command class knows how to perform its task, given a list
of arguments. The arguments are handled uniquely by each command
class. Some do not take arguments and perform a simple task. The
JSwatCommand
class knows how to print help information
about all of the commands. This is meant to assist the user in
understanding the basic syntax and use for a command. There is no
limit on the amount of help information a command can have. The
JSwatCommand
class also supports the display of a
short description of each command, useful in generated the
'help commands
' output.
The CommandManager
class supports command aliases.
That is, a new name can be given to a command, possibly with
default arguments. For instance, the user might be able to alias
'where all
' to 'wa
', thus
saving several keystrokes. These aliases are simply strings that
are substituted into any commands with the matching alias name.
The MacroManager
class supports command macros.
That is, a name can be given to group of commands which are then
executed each time the macro is invoked. For instance, the user
might be able to create a macro that sets the classpath and then
invokes 'view
' on a class, thus saving
numerous keystrokes. These macros are simply a set of strings that
are processed whenever the macro name is used.
The CommandManager
class supports a command history
chain. That is, as each command is input by the user it is saved in
a list. Later the user can use "!!" or
"!<prefix>" to run previously entered commands,
much like many Unix shell programs. Typing the command
"history" will display the command history. In the
graphical mode of JSwat, the command input field allows the use of
Ctrl-p
or Ctrl-n
(or the up/down cursor
keys) to navigate through the command history.
The CommandManager
class supports the concept of
unique command prefixes. That is, if the user types a command name
that does not match any of the known commands, the
CommandManager
will search for commands that have a
matching name prefix. For instance, if the user types
'att
' that will uniquely match
'attach
'. If instead the user types
'al
', that will result in an ambiguous match
with the commands 'alias
' and
'aliases
' (and possibly other commands, as
well). The CommandManager
will list any ambiguous
matches and expect the user to reenter the command using a unique
prefix, or possibly the full command name.