This might help with the shell, parts apply to all of JNode

Project:JNode Core
Component:Code
Category:task
Priority:normal
Assigned:Unassigned
Status:won't fix
Description

I understand the current system of org.jnode.shell.CommandLine and org.jnode.shell.help.* are already in place. However I think they are seriously flawed by design. Rather than placing the burdon on the App to return completion information and process the commands, wouldn't it work better to let the shell handle all that?

The CpCommand should be able to run in MS Win JVM, or Linux JVM, as well as in JNode. This applies to all commands, Cat, Grep, Diff, with the exception of a few, like fdisk, which depend on the OS API.

I propose the answer is a new list and a new command. The shell keeps a list of commands and args, this should be in a generic form (xml?) and specify the command, version, and it's optional args. That way a non-JNode app can still support command completion. System Admins could use it to help keep users from accidently using dangerous commands, and you could customize it to the options you use most.

The List

This list is maintained by the shell and contains the name, version and params for a command, this will allow a user to edit them if they want different command line completions. This list should import/export as simple generic style, maybe xml. It is internal to the shell so it doesn't matter how the shell wants to handle it internally.

The file format can be, maybe a string like,
    "CpCommand\t1.6\t[none[],help[-h],help; verbose[-help],copy[verbosity[-s,-v,-V] [url,file]* [file,dir]]]"
or xml like,
    <command alias="CpCommand" class="org.jnode.shell.command.CpCommand" version="1.6">
        <paramlist desc="none"/>
        <paramlist desc="help">
            <param value="-h"/>
        </paramlist>
        <paramlist desc="help; verbose">
            <param value="-help"/>
        </paramlist>
        <paramlist desc="copy">
            <optionlist desc="verbosity">
                <option value="-s" desc="silent"/>
                <option value="-v" desc="normal"/>
                <option value="-V" desc="verbose"/>
            </optionlist>
            <param type="url,file" desc="source file" multiple="true"/>
            <param type="file,dir" desc="destination"/>
        </paramlist>
    </command>

These can also be wrapped with a language code to assist with internationalization, as they can also be joined as strings "cat commandcomplete.txt mycommands.txt > newcommands.txt" with little ill effects.

The Command

The command will allow you to scan a class, jar, directory, or sub-directories for updates to the list. This command is looking for a method call XYZ, maybe getJnodeShellInfo() and will return a String. This string will contain at least the command and version. If a listing for the command and version are not in the list one is added. if a conflicting duplicate is found the user is shown the diff and prompted by the user which to use. This command can also be used to remove deleted commands from the list

The Shell

I propose that the shell internally keeps TWO list of commands and args. The first is a cache of the commands and the default params, the second is the user modified list. These two list should be exportable and importable in a generic form, xml, and specify the command, and it's optional params. When a command is entered it can be checked from cache, if not found the class, jar, etc can be scanned for the getJnodeShellInfo() method and if found update the cache.

The Unsupported Commands

If an app or command wasn't written for JNode, as many are not, then a developer/user supplied command completion file can be supplied. I personally recommend all should be made like this, that way these commands can be used outside of JNode.

RANT =====-----

This API needs to be defined better than it is. I'm finding many high level applications using JNode dependant packages. Develop your code outside of JNode when at all possible, and remember where you are operating. If I understand correctly there are 4 areas which are, Kernel, plugins and devices, the JNode OS and shell, and then applications. If your code lives in one place it should NOT work in another. Use the API, not internal structures.

Most commands should be able to run in MS Win JVM, or Linux JVM, as well as in JNode. This applies to all commands, Cat, Grep, Diff; with the exception of a few like fdisk, which depend on the OS API.

I will use EchoCommand as an example. It does not depend on JNode and should not be written as it is in JNode. It should be as follows:

public class EchoCommand {
    public static void main(String[] args) {
        if (args.length > 0) {
            System.out.print(args[0]);
            for (int i = 1; i < args.length; i++) {
                System.out.print(" " + args[i]);
            }
        }
        System.out.println();
    }
}

I think you have misunderstood something ...

The current command does not require the command to do completion and argument processing. On the contrary, the vast majority of the work is done by the Help/Syntax/Parameter/Argument classes. All an application needs to do is 'declare' the command syntax(es), call the 'parse' method and then look in the resulting data structure for the bound argument values.

Why re-invent the wheel?

And you don't see that as a problem? These are simple commands that should run on a linux or windows box, without JNode. Everything needed for the copy command exist in the JDK1.0, why re-invent the wheel?

No I don't see it as a problem

The reason we have CpCommand, EchoCommand, etc etc on JNode is that the Linux versions won't run here. And that is because JNode is a Java-only platform. In a sense, we have to invent the wheel of UNIX cp, echo, etc in Java.

But if I am running Linux, I can use the native cp, echo and so on. And if I'm running Windows I can install Cygwin, or similar. I wouldn't want to use a (portable) CpCommand because the overheads of launching a JVM to run it are prohibitive. (And if I did, I'd probably want to stay in the JVM and run CpCommand using a JNode shell.)

The "problem" (if you can call it that) is with larger command-line applications that we really want to run both in JNode and in Linux. Here are some possible approaches:

  1. Write the application with an <App>.main method that does its argument processing in old fashioned way. Then write a JNode-specific <App>Launcher class that implements Command and provides a Help.Info description of its syntax. The <App>Launcher.executeCommand method on the launcher class calls parse, extracts argument values from the result, and calls the <App>.main method.
  2. As above except that the <App>.main and <App>Launcher.executeCommand methods both call another method on the <App> class.
  3. Instead of an application-specific launcher, encode the descriptions in XML and write a "universal" launcher that uses reflection to instantiate Help/Syntax/Parameter/Argument objects, parse/match the command arguments and then call an <App> method as above.
  4. Create "compatibility" versions of the relevant JNode classes that can be used when the application is run on a classical JVM. (This may require some refactoring of the classes to avoid unwanted dependencies.)

Another point that needs to be made is that JNode's command syntax classes result in uniform treatment of arguments, and sophisticated command completion. Contrast this with classic Java apps (and UNIX apps) that do their own thing, leading to all sorts of inconsistencies in command syntax, usage messages and so on.

#1

Status:active» won't fix

The command syntax rewrite I mentioned is now well underway. I'm marking this task as "won't fix" because I am not going to adopt most the submitter's technical suggestions ... at least not in this iteration. However, I am using XML to specify syntax, and I am working on making the APIs better specified.