The Command API is currently...

    public void execute(String command, PrintStream out, PrintStream err)

After having written a few commands, I find myself doing two things a lot.

Firstly, I find myself parsing command-lines.

Currently all my parameters are whitespace-free but that's about to
change.  So now I need a full parser which handles quotes in a
sensible fashion consistent with my other commands, and indeed Felix's
existing commands.

It seems like the ultimate solution to this part would have been to
pass the command as a String[] instead of the raw command.  Obviously
I can write my own convenience API for this, but I started wondering
if Felix is already hiding something like this..?

Secondly, I find myself wondering how to handle sub-commands.  And
this is where the mail gets big.  Sorry about that.  for tl;dr types,
scroll down to my proposed interfaces and points below those.

Effectively having solved the parser problem already (which I haven't
solved correctly actually, but for the sake of discussion - the real
code splits on \s+) I now find myself implementing my own sub-command
framework.

Main problems:

* For getUsage() to contain a full description of what my top-level
command can do, it takes multiple lines.  But Felix then shows the
whole thing from the help command.
* Putting all the commands as methods on one class starts to become
unmanageable and then you create a sub-command API, and:
* The API for sub-commands looks awfully similar to the API for commands.

Possible resolution:

In my case I went with the main command parsing its first argument and
then switching to different methods.

I started wondering if there was a "proper" way to do this, and on
investigation I see other commands doing this all themselves too, like
"obr help".  Why not invert it?  Can't "help" show obr in the list
with a getShortUsage(), and then "help obr" shows the list of
sub-commands?  You could almost allow getName() to contain spaces and
then improve the shell to do better matching.  Or you could have an
explicit API for getting the sub-commands for a given command, and
then each one can have shortUsage and fullUsage.

I don't want to turn this into a "let's design a Command API"
discussion, but _if_ I were writing a new command API from scratch, I
guess ideally I would like to see this bare minimum:

    public interface Command {

        // If a top-level service comment then this needs to be unique
in the shell service.
        String getName();

        // "help" or "help obr" would show these:
        String getShortUsage();
        String getShortDescription();

        // "help obr list" would show these:
        String getFullUsage();
        String getFullDescription();

        /**
         * Executes a command.
         *
         * @param context the context in which the command is being
run.  All parameters passed through here.
         */
        public void execute(CommandContext context);

        /**
         * Gets all sub-commands.  These are commands where {...@link 
#getName()}
         * would return the name of the sub-command,
         */
        Command[] getSubCommands();
    }

    public interface CommandContext {
        String getCommandLine();
        String[] getCommand();
        PrintStream getErrorStream();
        PrintStream getOutputStream();
    }

Good points:
* You can extend the context later without disrupting the API

Deficiencies:
* On the other hand extending the *context* isn't possible.  Commons
Chain solves this for their command model by going all out and just
putting a map in there, which is possibly too much.  (And well,
they're not a shell either.  So you would have to pass out and err
streams as parameters too, to actually use that.)
* Still passes the full command in the parameters.  Purists would say
this is pointless and that it would be more reusable if it only passed
the parameters, which would make it possible to change the location of
commands in the tree without rewriting the command.

But... why develop a brand new command API?  There are already two
good ones out there which I'm aware of...

1. GShell's Command API - GShell is also in itself a good shell too,
with proper autocompletion for commands, and this is exposed
throughout the API as well.

2. JNode's Command API -  I have seen people tout JNode's as being
better than GShell... but it is LGPL but JNode have never really
advertised their code base as a collection of reusable components.

Both of these are trying to solve the same problem of making a generic
API where commands, help, completion and everything are considered.  I
would say JNode's is marginally better because if its notion of
argument types.

I guess what I'm wondering is, was there a particular reason Felix's
is the way it is, or is it because the codebase was pull in from
wherever and nobody has really used it intensively yet?


TX

P.S.   And on a side-note... I have been wondering how to get
user-level access control for commands, to control who can do what.

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to