Please help with shell cmdline parsing
I am having problems understanding what is happening within the cmdline parsing
part of the shell, just when I think that I have it sorted, it stops working. I
can get a given Syntax to work by itself but not together.
This is a simple bit of test code that I have taken from a class I am working
on to be able to pass a classpath/jar to the Java command and have other
classes included when loading the app. It expects either:
shelltest.ParameterTest -jar test.jar
shelltest.ParameterTest -cp test.jar:. test.Main
or
shelltest.ParameterTest test.Main
The true/false outputs are not consistant with what I would expect, any help
would be much appreciated. See code below for details (sorry about the formating).
TIA
Mark
/*
* Created on 4/02/2004
*/
package shelltest;
import org.jnode.shell.help.Argument;
import org.jnode.shell.help.Help;
import org.jnode.shell.help.OptionArgument;
import org.jnode.shell.help.Parameter;
import org.jnode.shell.help.ParsedArguments;
import org.jnode.shell.help.Syntax;
public class ParameterTest {
static final OptionArgument ARG_JAR_SWITCH =
new OptionArgument(
"jar",
"jar switch",
new OptionArgument.Option[] {
new OptionArgument.Option("-jar", "to execute a jar
file")});
static final Argument ARG_JAR = new Argument("jar", "the jar file to
execute");
static final OptionArgument ARG_CLASSPATH_SWITCH =
new OptionArgument(
"cp",
"classpath switch",
new OptionArgument.Option[] {
new OptionArgument.Option("-cp", "class search path of
directories and zip/jar files")});
static final Argument ARG_CLASSPATH = new Argument("classpath", "the value
of the classpath");
static final Argument ARG_CLASS = new Argument("classname", "the class to
excute");
static final Argument ARG_ARGS = new Argument("arg", "the argument(s) to
pass to the class", Argument.MULTI);
static final Parameter PARAM_CLASSPATH_SWITCH = new
Parameter(ARG_CLASSPATH_SWITCH, Parameter.MANDATORY);
static final Parameter PARAM_CLASSPATH = new Parameter(ARG_CLASSPATH,
Parameter.MANDATORY);
static final Parameter PARAM_JAR_SWITCH = new Parameter(ARG_JAR_SWITCH,
Parameter.MANDATORY);
static final Parameter PARAM_JAR = new Parameter(ARG_JAR,
Parameter.MANDATORY);
static final Parameter PARAM_CLASS = new Parameter(ARG_CLASS,
Parameter.MANDATORY);
static final Parameter PARAM_ARGS = new Parameter(ARG_ARGS,
Parameter.OPTIONAL);
public static Help.Info HELP_INFO = new Help.Info(
"java",
new Syntax[] {
new Syntax(
"Execute the main method of the given jar file",
new Parameter[]{
PARAM_JAR_SWITCH,
PARAM_JAR,
PARAM_ARGS
}),
new Syntax(
"Execute the main method of the given java
class from the given classpath",
new Parameter[]{
PARAM_CLASSPATH_SWITCH,
PARAM_CLASSPATH,
PARAM_CLASS,
PARAM_ARGS
}),
new Syntax(
"Execute the main method of the given java
class",
new Parameter[]{
PARAM_CLASS,
PARAM_ARGS
})
}
);
public static void main(String[] args) {
if (args.length != 0) {
ParsedArguments parsedArguments = HELP_INFO.parse(args);
System.out.println(PARAM_JAR_SWITCH.isSet(parsedArguments));
System.out.println(PARAM_CLASSPATH_SWITCH.isSet(parsedArguments));
}
}
}
- Login to post comments
Problem solved!
After some pointers from Michael Klaus on the usage of Argument and Parameter and reading through the code for Syntax I managed to solve my problems.
Seems that the code to handle -cp type args was commented out in Syntax and enabling the commented code made it all work.
This makes
java -cp a.jar a.Main
java -jar b.jar
java Main
all work OK.
So now I have a java command that can load classes from the classpath (from a dir or jar or a mix) and can execute a properly constructed jar.
Command Line?
I joined the jnode project shortly before 0.1.5, so you may hava already had this discussion...
What are thre great benifits of a command line that are driving you (all) to implement one. It is not object oriented. Infact a command line would be the most prominant example of pre-oo design found in jnode. Aargument cheching is dificult and cumbersome as is shown by the complexity of the Syntax classes.
Why was it not chosen, simply to uses the beanshell. It is oo, and argument cheching, would obviously be unneccessary. More important is this...
Learing to use a shell in a unix envirionment is similar to learing a language. Infact considering the similarity between Perl and a unix shell, you nearly have learned a language. It takes a lot of time, and reference matterial for a beginer to become proficient on a shell.
Jnode is an os for java developers, the more java we show them, the less they will have to learn, the happier they will be. It takes about four seconds to start using beansshell. "Hm? It's a java interpriter. OK." No matter how simple and elegent the command line is you can't compete with "Hm? ... OK."
Beanshell commands can be dynamically saved and loaded wich acounts for half of the 'aliasing' concept. The other half is accounded for by the extensibility of beanshell methods. Also the save/load commands serialize objects. This is excellent in the light of the oodb filesystem that has been spoken of.
What do you (all) think?
Benefits of a command line
Should we eliminate something useful just because it is old? Take a closer look at your web browser. Examine the location field. It is a command line. Do you think that a web browser, such as Lobo, should be included in a modern operating system? Then, I could actually use JNode to get my work done.
You want to tell your computer what to do; you want to command it. You might prefer to command it using a web browser. A web browser is an example of a shell. Others might prefer to command it using a simple text-based command line interpreter, another example of a shell. A shell has properties, such as current directory, environment variables. Each shell has its own way of interpreting the command line.
An object oriented programming language or object oriented design does not eliminate the need for a command line. Although your favorite browser greatly enhances a command line, it does not eliminate it. Occasionally, we copy, cut, paste a location. When you display a page in your browser, it becomes the default context for additional commands on that page. The HTTP service is responsible for invoking the command line.
I believe that a familiar, traditional shell is critically important to an operating system. A command-line "browser" would enable you to display a list of commands, select a command, and display a fill-in-the-blank form to provide the parameters for a command. How do we select a command? How do we go back to the previous command? How do we select parameters? How does the browser construct a fill-in-the-blank form for parameters? Does metadata come from a command class? Does it come from resources external to the command class? Coming full circle, a command-line browser (shell) is responsible for implementing these features.
Don't worry ...
No matter what some folks think, JNode has a command line and will continue to have one. Indeed, I'm working on some major improvements at the moment. For example, I'm working on a way to specify a command's syntax(es) independently of the Java code that implements the command.
As I know beanshell is included into jnode or not?
As I know beanshell is included into jnode or not? I don't know beanshell but I have a question..how do I dir a folder? how do I print a text file to the console? how do I delete a file? Don't tell me throgh java code coze not everyone is a java developer you know. I agree that beenshell should be there but a commandline is a MUST. JNode is not just an experiment we hope peoples will use JNode in real life work and not look at it like an experiment
Hasn't bean shell been broken
I haven't been able to use it. See
http://jnode.sourceforge.net/portal/node/view/120
Has anyone been able to get it to work.
weo
beanshell
dir(){
print(new File(bsh.cwd).listFiles());
}
The commands you listed are neccessary but they must all be implemented in the command line anyway. I only suggest we move development from cmd to the beanshell. After the neccessary functions are implemented the beanshell could work like a cmdln. The onle diference would be the '();'
cd("/mydir/myOtherDir");
dir();
cat("someFile");
These commands take a few more strokes to type, but consider some of the realy huge functions in unix. Starting the samba server in redhat takes at least three arguments, non of which is distingishable in the --help printout. Such a method would have formal parramiter types in beanshell. Infact it would probably be better to use the nesting capability and provide several overloaded methods inside a 'class.'
I think that it is posible to use the beanshell like a command line.
This would preserve all of the conciceness of the cmd but remove it's most fatal flaw ("Text only please").
What do you think?
command line completition
hi, how do we provide command line completition than? Change beanshell?and by the way I don't think cd("/mydir/myOtherDir"); is an acceptable solution for a non IT profesional user. Only maybe if we have a great GUI interface ...
Completion
Beanshell suplies a type of name completion for package and class names, not methods or fields. When the name completion feature is uesd, the output ruins the working line, so that you have to type the line again.
This I believe will be made better in later versions. Until then, we could take it on ourselves to fix it (beanshell is available under lgnpl and the spl.) or we could implement methods like these.
methods(){
print(super.methods);
}
variables(){
print(super.variables);
}
This is not actual completion but it provides the neccessary information.
The jnodeShell could be as powerful and feature filled as the developers who work with it. Every time a developer writes a helper method, the jShell becomes more usefull. The reality of a dynamically extensible shell has never before been realized.
What do you think?
Beanshell
I totally agree. It should also be quite easy to modify the existing commands and make them beanshell scripts.
Adding bsh support to existing shell commands
I have looked into how the existing shell commands can be plugged into bsh. It is easy. All that needs to be done is to add a method of the form
public static void invoke(bsh.Interpreter env, bsh.CallStack callstack, String arg1, String arg2, ...)
to a command class.
E.g. to CpuIDCommand, just add
public static void invoke(bsh.Interpreter env, bsh.CallStack callstack) {
new CpuIDCommand().execute(null, null, env.getOut(), env.getErr());
}
Then, in bsh
importCommands("org.jnode.shell.command");
CpuIDCommand();
The importCommands step can be avoided be adding
interpreter.eval("importCommands(\"org.jnode.shell.command\")");
to the appropriate place in BeanshellCommand.java.
I agree as well.
I agree too but who will do that? will you? I think the idea is very good and if it works we should remove the curent shell comletly.
Design
I can contribute. I can lead, if that is desired, but I will need help. Three things need to be done to get started.
1 Whatever code in the boot sequence that starts the command prompt, needs to be replaced with starter code for the beanshell. I cannot do this alone. I have looked over the code but I didn't get the jump from the Main.exicute() to the initjar. I will need help.
2 The existing commands need to have the invoke() method added to them as has already been said. I might be able to do this if I studied the code, but it would be faster if the people who wrote the code did it themselves.
3 We need to design and maintain a set of familar functions like cat, and grep, though I believe we should give them a more java-like name. We could always have a method with a unix name call the java-like method. Something like cat() calls printFile().
That way both methods will show in a method list, and more people will know how to use the console.
These are the most important issues. As a side note, I have been looking into the proccess of saving just one method from a beanshell, instead of the whole interpreter. If a user defined a helper method like countChars() he could save it without saving the rest of the methods, wich he may not want. The method deffinition would be saved in a specified (or default) command directory, where it could be imported from later.
This functionality is a kind of internal development. It would make woriking in jnode a little easier.
I am going to open a thread in the Jnode-Shell forum call BeanShell.
If you have any questions or you know how to help, respond there.
Have you checked this in?
I also have problems with this classes maybe you could write a small tutorial about how to use this. we can post it on the site so that peoples won't be needed to rediscover how this works.
regards,
Valentin
We baaaadly need this tutorial
Is anyone writing documentation about Arguments and Parameters etc?
Help package documentation
Looks like I'd be able to do some work on JNode again, finally I'll try to get a working version as soon as possible and start testing/documenting the package. What's the preferred format? A howto, example, better javadoc? Please feed back. I'll do my best to give you people a comprehensive doc.
To the BeanShell topic: It's a quite nice thing to have an OO capable shell. The problem (for me) is the overhead in typing that's introduced. There's nothing bad to additionally providing such a possibility. Thinkin about
bsh 'dir("/var/log")'
or such, maybe even a 1 character shortcut. But we shouldn't erase the possibility to be _somawhat_ compatible with what's heavily used in current IT, namely simple, most-quickly typable command shell language; be it (ba)sh, csh or batch.
The more existing code we're able to run, the more business cases JNode will be of use for.