|
From: <cr...@us...> - 2008-11-16 02:53:12
|
Revision: 4703
http://jnode.svn.sourceforge.net/jnode/?rev=4703&view=rev
Author: crawley
Date: 2008-11-16 02:53:07 +0000 (Sun, 16 Nov 2008)
Log Message:
-----------
Overhaul the help subsystem to make it easier to hook in ESC help, and
support anticipated future developments. This also addresses a previously
unnoticed problem where HelpCommand triggered class loading for all known
aliases, and improves diagnostics for class load failure. This checkin
will probably break 'old' syntax command completion (see issue #2802) but
AFAIK, there are no extant commands using the 'old' syntax mechanism.
Modified Paths:
--------------
trunk/distr/src/emu/org/jnode/emu/Emu.java
trunk/shell/src/shell/org/jnode/shell/CommandLine.java
trunk/shell/src/shell/org/jnode/shell/CommandRunner.java
trunk/shell/src/shell/org/jnode/shell/CommandShell.java
trunk/shell/src/shell/org/jnode/shell/DefaultCommandInvoker.java
trunk/shell/src/shell/org/jnode/shell/command/HelpCommand.java
trunk/shell/src/shell/org/jnode/shell/help/Argument.java
trunk/shell/src/shell/org/jnode/shell/help/CommandLineElement.java
trunk/shell/src/shell/org/jnode/shell/help/Help.java
trunk/shell/src/shell/org/jnode/shell/help/Parameter.java
trunk/shell/src/shell/org/jnode/shell/help/argument/EnumOptionArgument.java
trunk/shell/src/shell/org/jnode/shell/help/argument/OptionArgument.java
trunk/shell/src/shell/org/jnode/shell/help/def/SystemHelpPlugin.java
trunk/shell/src/test/org/jnode/test/shell/Cassowary.java
trunk/shell/src/test/org/jnode/test/shell/help/DefaultHelpTest.java
trunk/shell/src/test/org/jnode/test/shell/syntax/AlternativesSyntaxTest.java
trunk/shell/src/test/org/jnode/test/shell/syntax/OptionSyntaxTest.java
trunk/shell/src/test/org/jnode/test/shell/syntax/PowersetSyntaxTest.java
trunk/shell/src/test/org/jnode/test/shell/syntax/RepeatedSyntaxTest.java
trunk/shell/src/test/org/jnode/test/shell/syntax/SequenceSyntaxTest.java
Added Paths:
-----------
trunk/shell/src/shell/org/jnode/shell/help/EnhancedHelp.java
trunk/shell/src/shell/org/jnode/shell/help/HelpFactory.java
trunk/shell/src/shell/org/jnode/shell/help/def/DefaultHelpFactory.java
trunk/shell/src/shell/org/jnode/shell/help/def/NewSyntaxHelp.java
trunk/shell/src/shell/org/jnode/shell/help/def/OldSyntaxHelp.java
trunk/shell/src/shell/org/jnode/shell/help/def/TextHelpBase.java
Removed Paths:
-------------
trunk/shell/src/shell/org/jnode/shell/help/def/DefaultHelp.java
Modified: trunk/distr/src/emu/org/jnode/emu/Emu.java
===================================================================
--- trunk/distr/src/emu/org/jnode/emu/Emu.java 2008-11-12 13:47:18 UTC (rev 4702)
+++ trunk/distr/src/emu/org/jnode/emu/Emu.java 2008-11-16 02:53:07 UTC (rev 4703)
@@ -19,8 +19,8 @@
import org.jnode.shell.alias.AliasManager;
import org.jnode.shell.alias.def.DefaultAliasManager;
import org.jnode.shell.def.DefaultShellManager;
-import org.jnode.shell.help.Help;
-import org.jnode.shell.help.def.DefaultHelp;
+import org.jnode.shell.help.HelpFactory;
+import org.jnode.shell.help.def.DefaultHelpFactory;
import org.jnode.shell.syntax.DefaultSyntaxManager;
import org.jnode.shell.syntax.SyntaxBundle;
import org.jnode.shell.syntax.SyntaxManager;
@@ -93,7 +93,7 @@
InitialNaming.bind(AliasManager.NAME, aliasMgr);
InitialNaming.bind(ShellManager.NAME, new DefaultShellManager());
InitialNaming.bind(SyntaxManager.NAME, syntaxMgr);
- InitialNaming.bind(Help.NAME, new DefaultHelp());
+ InitialNaming.bind(HelpFactory.NAME, new DefaultHelpFactory());
} catch (NamingException ex) {
throw new EmuException("Problem setting up InitialNaming bindings", ex);
}
Modified: trunk/shell/src/shell/org/jnode/shell/CommandLine.java
===================================================================
--- trunk/shell/src/shell/org/jnode/shell/CommandLine.java 2008-11-12 13:47:18 UTC (rev 4702)
+++ trunk/shell/src/shell/org/jnode/shell/CommandLine.java 2008-11-16 02:53:07 UTC (rev 4703)
@@ -27,6 +27,7 @@
import org.jnode.shell.help.CompletionException;
import org.jnode.shell.help.Help;
import org.jnode.shell.help.HelpException;
+import org.jnode.shell.help.HelpFactory;
import org.jnode.shell.help.Parameter;
import org.jnode.shell.io.CommandIO;
import org.jnode.shell.io.CommandIOMarker;
@@ -643,7 +644,7 @@
} else {
// Otherwise, try old-style completion using the command's INFO
try {
- Help.Info info = Help.getInfo(cmdClass.getCommandClass());
+ Help.Info info = HelpFactory.getInfo(cmdClass.getCommandClass());
info.complete(completion, this, shell.getOut());
} catch (HelpException ex) {
// And fall back to old-style completion with an 'info' that
Modified: trunk/shell/src/shell/org/jnode/shell/CommandRunner.java
===================================================================
--- trunk/shell/src/shell/org/jnode/shell/CommandRunner.java 2008-11-12 13:47:18 UTC (rev 4702)
+++ trunk/shell/src/shell/org/jnode/shell/CommandRunner.java 2008-11-16 02:53:07 UTC (rev 4703)
@@ -30,7 +30,7 @@
import java.security.AccessController;
import java.security.PrivilegedActionException;
-import org.jnode.shell.help.Help;
+import org.jnode.shell.help.HelpFactory;
import org.jnode.shell.help.HelpException;
import org.jnode.shell.help.SyntaxErrorException;
import org.jnode.shell.io.CommandIO;
@@ -144,7 +144,7 @@
}
} catch (SyntaxErrorException ex) {
try {
- Help.getInfo(cmdInfo.getCommandClass()).usage(shellErr);
+ HelpFactory.getInfo(cmdInfo.getCommandClass()).usage(shellErr);
shellErr.println(ex.getMessage());
} catch (HelpException e) {
shellErr.println("Exception while trying to get the command usage");
Modified: trunk/shell/src/shell/org/jnode/shell/CommandShell.java
===================================================================
--- trunk/shell/src/shell/org/jnode/shell/CommandShell.java 2008-11-12 13:47:18 UTC (rev 4702)
+++ trunk/shell/src/shell/org/jnode/shell/CommandShell.java 2008-11-16 02:53:07 UTC (rev 4703)
@@ -55,7 +55,6 @@
import org.jnode.naming.InitialNaming;
import org.jnode.shell.alias.AliasManager;
import org.jnode.shell.alias.NoSuchAliasException;
-import org.jnode.shell.help.CompletionException;
import org.jnode.shell.io.CommandIO;
import org.jnode.shell.io.CommandInput;
import org.jnode.shell.io.CommandInputOutput;
Modified: trunk/shell/src/shell/org/jnode/shell/DefaultCommandInvoker.java
===================================================================
--- trunk/shell/src/shell/org/jnode/shell/DefaultCommandInvoker.java 2008-11-12 13:47:18 UTC (rev 4702)
+++ trunk/shell/src/shell/org/jnode/shell/DefaultCommandInvoker.java 2008-11-16 02:53:07 UTC (rev 4703)
@@ -30,7 +30,7 @@
import java.security.PrivilegedAction;
import java.security.PrivilegedActionException;
-import org.jnode.shell.help.Help;
+import org.jnode.shell.help.HelpFactory;
import org.jnode.shell.help.SyntaxErrorException;
import org.jnode.shell.io.CommandIO;
import org.jnode.vm.VmExit;
@@ -117,7 +117,7 @@
}
}
} catch (SyntaxErrorException ex) {
- Help.getInfo(cmdInfo.getCommandClass()).usage(err);
+ HelpFactory.getInfo(cmdInfo.getCommandClass()).usage(err);
err.println(ex.getMessage());
} catch (VmExit ex) {
return ex.getStatus();
Modified: trunk/shell/src/shell/org/jnode/shell/command/HelpCommand.java
===================================================================
--- trunk/shell/src/shell/org/jnode/shell/command/HelpCommand.java 2008-11-12 13:47:18 UTC (rev 4702)
+++ trunk/shell/src/shell/org/jnode/shell/command/HelpCommand.java 2008-11-16 02:53:07 UTC (rev 4703)
@@ -26,18 +26,17 @@
import javax.naming.NameNotFoundException;
import org.jnode.shell.AbstractCommand;
+import org.jnode.shell.CommandInfo;
import org.jnode.shell.CommandLine;
-import org.jnode.shell.Shell;
+import org.jnode.shell.CommandShell;
import org.jnode.shell.ShellUtils;
import org.jnode.shell.alias.AliasManager;
import org.jnode.shell.alias.NoSuchAliasException;
import org.jnode.shell.help.Help;
+import org.jnode.shell.help.HelpFactory;
import org.jnode.shell.help.HelpException;
import org.jnode.shell.syntax.AliasArgument;
import org.jnode.shell.syntax.Argument;
-import org.jnode.shell.syntax.ArgumentBundle;
-import org.jnode.shell.syntax.SyntaxBundle;
-import org.jnode.shell.syntax.SyntaxManager;
/**
* @author qades
@@ -59,7 +58,9 @@
}
@Override
- public void execute() throws Exception {
+ public void execute() throws NameNotFoundException, ClassNotFoundException, NoSuchAliasException {
+ // The above exceptions are either bugs or configuration errors and should be allowed
+ // to propagate so that the shell can diagnose them appropriately.
String alias;
CommandLine commandLine = getCommandLine();
PrintWriter out = getOutput().getPrintWriter();
@@ -71,108 +72,53 @@
} else {
alias = "help";
}
-
- Help.Info info = null;
- SyntaxBundle syntaxes = null;
- ArgumentBundle bundle = null;
- String otherAliases = null;
+ CommandShell shell = null;
try {
- final Shell shell = ShellUtils.getShellManager().getCurrentShell();
- final AliasManager aliasManager = shell.getAliasManager();
- final SyntaxManager syntaxManager = shell.getSyntaxManager();
- Class<?> clazz = getCommandClass(aliasManager, alias);
- bundle = getBundle(clazz, err);
- if (bundle != null) {
- syntaxes = syntaxManager.getSyntaxBundle(alias);
- if (syntaxes == null) {
- syntaxes = new SyntaxBundle(alias, bundle.createDefaultSyntax());
- }
- } else {
- info = Help.getInfo(clazz);
- }
- if (info != null || syntaxes != null) {
- otherAliases = getOtherAliases(aliasManager, alias, clazz);
- }
- } catch (ClassNotFoundException ex) {
- err.println("Alias not found: " + alias);
- exit(1);
- } catch (SecurityException ex) {
- err.println("Access to class prevented by security manager");
- exit(2);
- } catch (NameNotFoundException ex) {
- err.println("Can't find the shell manager");
- exit(2);
+ shell = (CommandShell) ShellUtils.getShellManager().getCurrentShell();
+ CommandInfo cmdInfo = shell.getCommandInfo(alias);
+ Help cmdHelp = HelpFactory.getHelpFactory().getHelp(alias, shell.getCommandInfo(alias));
+ cmdHelp.help(out);
+ otherAliases(shell.getAliasManager(), alias, cmdInfo.getCommandClass().getName(), out);
} catch (HelpException ex) {
- err.println("No help information available for alias " + alias);
+ err.println("No help information is available for alias / class '" + alias + "'");
exit(1);
+ } catch (ClassNotFoundException ex) {
+ try {
+ String className = shell.getAliasManager().getAliasClassName(alias);
+ err.println("Cannot load class '" + className + "' for alias '" + alias + "'");
+ } catch (NoSuchAliasException ex2) {
+ err.println("'" + alias + "' is neither an alias or a loadable class name");
+ }
+ throw ex;
+ } catch (SecurityException ex) {
+ err.println("Security exception while loading the class associated with alias '" + alias + "'");
+ err.println("Reported reason: " + ex.getLocalizedMessage());
+ throw ex;
}
-
- if (syntaxes != null) {
- Help.getHelp().help(syntaxes, bundle, out);
- } else if (info != null) {
- Help.getHelp().help(info, alias, out);
- } else {
- out.println("No help information available: " + alias);
- }
- if (otherAliases != null) {
- out.println(otherAliases);
- }
}
- private ArgumentBundle getBundle(Class<?> clazz, PrintWriter err) {
- try {
- AbstractCommand command = (AbstractCommand) clazz.newInstance();
- return command.getArgumentBundle();
- } catch (ClassCastException e) {
- // The target class cannot
- } catch (InstantiationException e) {
- err.println("Problem during instantiation of " + clazz.getName());
- exit(2);
- } catch (IllegalAccessException e) {
- err.println("Constructor for " + clazz.getName() + " is not accessible");
- exit(2);
- }
- return null;
- }
+ private void otherAliases(AliasManager aliasManager, String thisAlias,
+ String aliasClass, PrintWriter out) throws NoSuchAliasException {
+ // NoSuchAliasException indicates a bug, and should be allowed to propagate.
+ StringBuilder sb = new StringBuilder();
- private Class<?> getCommandClass(AliasManager aliasManager, String commandName)
- throws ClassNotFoundException {
- try {
- return aliasManager.getAliasClass(commandName);
- } catch (NoSuchAliasException ex) {
- // Not an alias -> assuming it's a class name
- return Class.forName(commandName);
- }
- }
-
- private String getOtherAliases(AliasManager aliasManager, String alias, Class<?> aliasClass) {
- boolean hasOtherAlias = false;
- StringBuilder sb = new StringBuilder("Other aliases: ");
- boolean first = true;
-
for (String otherAlias : aliasManager.aliases()) {
- // exclude alias from the returned list
- if (!otherAlias.equals(alias)) {
- try {
- Class<?> otherAliasClass = aliasManager.getAliasClass(otherAlias);
-
- if (aliasClass.equals(otherAliasClass)) {
- // we have found another alias for the same command
- hasOtherAlias = true;
- if (!first) {
- sb.append(",");
- }
- sb.append(otherAlias);
- first = false;
+ // exclude thisAlias from the output
+ if (!otherAlias.equals(thisAlias)) {
+ String otherAliasClass = aliasManager.getAliasClassName(otherAlias);
+ // System.err.println("comparing '" + aliasClass + "' with '" + otherAliasClass + "'");
+ if (aliasClass.equals(otherAliasClass)) {
+ // we have found another alias for the same command
+ if (sb.length() > 0) {
+ sb.append(", ");
}
- } catch (NoSuchAliasException nsae) {
- // should never happen since we iterate on known aliases
- } catch (ClassNotFoundException e) {
- // should never happen since we iterate on known aliases
+ sb.append(otherAlias);
}
}
}
- return hasOtherAlias ? sb.toString() : null;
+ if (sb.length() > 0) {
+ out.println("Other aliases: " + sb);
+ }
}
}
Modified: trunk/shell/src/shell/org/jnode/shell/help/Argument.java
===================================================================
--- trunk/shell/src/shell/org/jnode/shell/help/Argument.java 2008-11-12 13:47:18 UTC (rev 4702)
+++ trunk/shell/src/shell/org/jnode/shell/help/Argument.java 2008-11-16 02:53:07 UTC (rev 4703)
@@ -55,7 +55,7 @@
return "<" + getName() + ">" + (isMulti() ? " ..." : "");
}
- public void describe(Help help, PrintWriter out) {
+ public void describe(HelpFactory help, PrintWriter out) {
help.describeArgument(this, out);
}
Modified: trunk/shell/src/shell/org/jnode/shell/help/CommandLineElement.java
===================================================================
--- trunk/shell/src/shell/org/jnode/shell/help/CommandLineElement.java 2008-11-12 13:47:18 UTC (rev 4702)
+++ trunk/shell/src/shell/org/jnode/shell/help/CommandLineElement.java 2008-11-16 02:53:07 UTC (rev 4703)
@@ -46,7 +46,7 @@
}
public abstract String format();
- public abstract void describe(Help help, PrintWriter out);
+ public abstract void describe(HelpFactory help, PrintWriter out);
public abstract void complete(CompletionInfo completion, String partial);
/**
Added: trunk/shell/src/shell/org/jnode/shell/help/EnhancedHelp.java
===================================================================
--- trunk/shell/src/shell/org/jnode/shell/help/EnhancedHelp.java (rev 0)
+++ trunk/shell/src/shell/org/jnode/shell/help/EnhancedHelp.java 2008-11-16 02:53:07 UTC (rev 4703)
@@ -0,0 +1,59 @@
+/*
+ * $Id: CommandLineElement.java 4556 2008-09-13 08:02:20Z crawley $
+ *
+ * JNode.org
+ * Copyright (C) 2003-2006 JNode.org
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; If not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+ package org.jnode.shell.help;
+
+import java.io.PrintWriter;
+
+/**
+ * This enhanced help interface provides extra fine-grained help
+ * methods.
+ *
+ * @author cr...@jn...
+ */
+public interface EnhancedHelp extends Help {
+ /**
+ * Output the description (summary) text for the command.
+ *
+ * @param pw the help information is written here
+ */
+ void description(PrintWriter pw);
+
+ /**
+ * Output the argument descriptions for the command.
+ *
+ * @param pw the help information is written here
+ */
+ public void arguments(PrintWriter pw);
+
+ /**
+ * Output the option descriptions for the command.
+ *
+ * @param pw the help information is written here
+ */
+ public void options(PrintWriter pw);
+
+ /**
+ * Output the detailed help text for the command.
+ *
+ * @param pw the help information is written here
+ */
+ public void details(PrintWriter pw);
+}
Modified: trunk/shell/src/shell/org/jnode/shell/help/Help.java
===================================================================
--- trunk/shell/src/shell/org/jnode/shell/help/Help.java 2008-11-12 13:47:18 UTC (rev 4702)
+++ trunk/shell/src/shell/org/jnode/shell/help/Help.java 2008-11-16 02:53:07 UTC (rev 4703)
@@ -18,118 +18,41 @@
* along with this library; If not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-
package org.jnode.shell.help;
import java.io.PrintWriter;
-import java.lang.reflect.Field;
-import java.util.TreeSet;
-import javax.naming.NamingException;
-
import org.jnode.driver.console.CompletionInfo;
-import org.jnode.naming.InitialNaming;
-import org.jnode.plugin.PluginUtils;
import org.jnode.shell.CommandLine;
-import org.jnode.shell.syntax.ArgumentBundle;
-import org.jnode.shell.syntax.FlagArgument;
-import org.jnode.shell.syntax.SyntaxBundle;
/**
- * @author qades
- * @author Fabien DUMINY (fd...@jn...)
+ * This is the interface for an object that outputs command help. Different
+ * implementations support different command syntax mechanisms, and (in the
+ * future) will provide help in different output formats; e.g. plain text,
+ * HTML and so on.
+ *
+ * @author cr...@jn...
*/
-public abstract class Help {
- public static final String BUNDLE_NAME = "messages"; // must be in our package
-
- public static final Class<Help> NAME = Help.class;
-
- public static final String INFO_FIELD_NAME = "HELP_INFO";
-
- public static Help getHelp() throws HelpException {
- try {
- return InitialNaming.lookup(NAME);
- } catch (NamingException ex) {
- throw new HelpException("Help application not found");
- }
- }
-
- public static String getLocalizedHelp(String messageKey) {
- return PluginUtils.getLocalizedMessage(Help.class,
- BUNDLE_NAME, messageKey);
- }
-
- public static Info getInfo(Class<?> clazz) throws HelpException {
- try {
- Field helpInfo = clazz.getField(INFO_FIELD_NAME);
- return (Help.Info) helpInfo.get(null); // static access
- } catch (NoSuchFieldException ex) {
- throw new HelpException("Command information not found");
- } catch (IllegalAccessException ex) {
- throw new HelpException("Command information not accessible");
- }
- }
-
+public interface Help {
+
/**
- * Shows the help page for a command
+ * Output complete help for the command.
*
- * @param info the command info
- * @param command a command name or alias which appears in the help
- * @param out the destination for help output.
+ * @param pw the help information is written here
*/
- public abstract void help(Info info, String command, PrintWriter out);
-
+ public void help(PrintWriter pw);
+
/**
- * Shows the help page for a command
+ * Output the usage message(s) for the command.
*
- * @param syntaxes the command's syntax bundle
- * @param bundle the command's argument bundle
- * @param out the destination for help output.
+ * @param pw the help information is written here
*/
- public abstract void help(SyntaxBundle syntaxes, ArgumentBundle bundle, PrintWriter out);
-
+ public void usage(PrintWriter pw);
+
/**
- * Shows the usage line for a command
- *
- * @param info the command information
- * @param out the destination for help output.
+ * This class is here for historical reasons. It is a key API class in the
+ * 'old' JNode syntax mechanism.
*/
- public abstract void usage(Info info, PrintWriter out);
-
- /**
- * Shows the usage line for a command
- *
- * @param syntaxes the command's syntax bundle
- * @param bundle the command's argument bundle
- * @param out the destination for help output.
- */
- public abstract void usage(SyntaxBundle syntaxes, ArgumentBundle bundle, PrintWriter out);
-
- /**
- * Shows the description of a single argument. Used as a callback in
- * {@link Argument#describe(Help)}.
- */
- public abstract void describeArgument(Argument arg, PrintWriter out);
-
- /**
- * Shows the description of a single argument. Used as a callback in
- * {@link Argument#describe(Help)}.
- */
- public abstract void describeArgument(org.jnode.shell.syntax.Argument<?> arg, PrintWriter out);
-
- /**
- * Shows the description of a single FlagArgument. Used as a callback in
- * {@link Argument#describe(Help)}.
- */
- public abstract void describeOption(FlagArgument arg,
- TreeSet<String> flagTokens, PrintWriter out);
-
- /**
- * Shows the description of a single parameter. Used as a callback in
- * {@link Parameter#describe(Help)}.
- */
- public abstract void describeParameter(Parameter param, PrintWriter out);
-
public static class Info {
private final String name;
@@ -161,7 +84,7 @@
public void usage(PrintWriter out) {
try {
- Help.getHelp().usage(this, out);
+ HelpFactory.getHelpFactory().usage(this, out);
} catch (HelpException ex) {
ex.printStackTrace();
}
@@ -173,7 +96,7 @@
* @throws HelpException
*/
public void help(String command, PrintWriter out) throws HelpException {
- Help.getHelp().help(this, command, out);
+ HelpFactory.getHelpFactory().help(this, command, out);
}
public String complete(CompletionInfo completion, CommandLine partial,
Added: trunk/shell/src/shell/org/jnode/shell/help/HelpFactory.java
===================================================================
--- trunk/shell/src/shell/org/jnode/shell/help/HelpFactory.java (rev 0)
+++ trunk/shell/src/shell/org/jnode/shell/help/HelpFactory.java 2008-11-16 02:53:07 UTC (rev 4703)
@@ -0,0 +1,152 @@
+/*
+ * $Id: Help.java 4556 2008-09-13 08:02:20Z crawley $
+ *
+ * JNode.org
+ * Copyright (C) 2003-2006 JNode.org
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; If not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+package org.jnode.shell.help;
+
+import java.io.PrintWriter;
+import java.lang.reflect.Field;
+import java.util.TreeSet;
+
+import javax.naming.NamingException;
+
+import org.jnode.naming.InitialNaming;
+import org.jnode.plugin.PluginUtils;
+import org.jnode.shell.CommandInfo;
+import org.jnode.shell.help.Help.Info;
+import org.jnode.shell.syntax.ArgumentBundle;
+import org.jnode.shell.syntax.FlagArgument;
+import org.jnode.shell.syntax.SyntaxBundle;
+
+/**
+ * The HelpFactory class is the base class for the Help factory classes, and provides
+ * a static method for getting the default factory. Other methods in this class are
+ * here for historical reasons, and should be avoided where possible.
+ *
+ * @author qades
+ * @author Fabien DUMINY (fd...@jn...)
+ * @author cr...@jn...
+ */
+public abstract class HelpFactory {
+ public static final String BUNDLE_NAME = "messages"; // must be in our package
+
+ public static final Class<HelpFactory> NAME = HelpFactory.class;
+
+ public static final String INFO_FIELD_NAME = "HELP_INFO";
+
+ public static HelpFactory getHelpFactory() throws HelpException {
+ try {
+ return InitialNaming.lookup(NAME);
+ } catch (NamingException ex) {
+ throw new HelpException("Help factory not found");
+ }
+ }
+
+ public static String getLocalizedHelp(String messageKey) {
+ return PluginUtils.getLocalizedMessage(HelpFactory.class,
+ BUNDLE_NAME, messageKey);
+ }
+
+ public static Info getInfo(Class<?> clazz) throws HelpException {
+ try {
+ Field helpInfo = clazz.getField(INFO_FIELD_NAME);
+ return (Help.Info) helpInfo.get(null); // static access
+ } catch (NoSuchFieldException ex) {
+ throw new HelpException("Command information not found");
+ } catch (IllegalAccessException ex) {
+ throw new HelpException("Command information not accessible");
+ }
+ }
+
+ /**
+ * Obtain a CommanHelp object for a given command alias and its resolved CommandInfo.
+ *
+ * @param alias
+ * @param cmdInfo
+ * @return
+ * @throws HelpException
+ */
+ public abstract Help getHelp(
+ String alias, CommandInfo cmdInfo) throws HelpException;
+
+ // FIXME ... the remaining API methods are historical, and should not be used outside of
+ // the help package and its implementation packages.
+
+ /**
+ * Shows the help page for a command
+ *
+ * @param info the command info
+ * @param command a command name or alias which appears in the help
+ * @param out the destination for help output.
+ */
+ protected abstract void help(Info info, String command, PrintWriter out);
+
+ /**
+ * Shows the help page for a command
+ *
+ * @param syntaxes the command's syntax bundle
+ * @param bundle the command's argument bundle
+ * @param out the destination for help output.
+ */
+ protected abstract void help(SyntaxBundle syntaxes, ArgumentBundle bundle, PrintWriter out);
+
+ /**
+ * Shows the usage line for a command
+ *
+ * @param info the command information
+ * @param out the destination for help output.
+ */
+ protected abstract void usage(Info info, PrintWriter out);
+
+ /**
+ * Shows the usage line for a command
+ *
+ * @param syntaxes the command's syntax bundle
+ * @param bundle the command's argument bundle
+ * @param out the destination for help output.
+ */
+ protected abstract void usage(SyntaxBundle syntaxes, ArgumentBundle bundle, PrintWriter out);
+
+ /**
+ * Shows the description of a single argument. Used as a callback in
+ * {@link Argument#describe(HelpFactory)}.
+ */
+ protected abstract void describeArgument(Argument arg, PrintWriter out);
+
+ /**
+ * Shows the description of a single argument. Used as a callback in
+ * {@link Argument#describe(HelpFactory)}.
+ */
+ protected abstract void describeArgument(org.jnode.shell.syntax.Argument<?> arg, PrintWriter out);
+
+ /**
+ * Shows the description of a single FlagArgument. Used as a callback in
+ * {@link Argument#describe(HelpFactory)}.
+ */
+ protected abstract void describeOption(FlagArgument arg,
+ TreeSet<String> flagTokens, PrintWriter out);
+
+ /**
+ * Shows the description of a single parameter. Used as a callback in
+ * {@link Parameter#describe(HelpFactory)}.
+ */
+ protected abstract void describeParameter(Parameter param, PrintWriter out);
+
+}
Modified: trunk/shell/src/shell/org/jnode/shell/help/Parameter.java
===================================================================
--- trunk/shell/src/shell/org/jnode/shell/help/Parameter.java 2008-11-12 13:47:18 UTC (rev 4702)
+++ trunk/shell/src/shell/org/jnode/shell/help/Parameter.java 2008-11-16 02:53:07 UTC (rev 4703)
@@ -105,7 +105,7 @@
return (optional ? "[" + result + "]" : result);
}
- public void describe(Help help, PrintWriter out) {
+ public void describe(HelpFactory help, PrintWriter out) {
if (!isAnonymous()) {
help.describeParameter(this, out);
}
Modified: trunk/shell/src/shell/org/jnode/shell/help/argument/EnumOptionArgument.java
===================================================================
--- trunk/shell/src/shell/org/jnode/shell/help/argument/EnumOptionArgument.java 2008-11-12 13:47:18 UTC (rev 4702)
+++ trunk/shell/src/shell/org/jnode/shell/help/argument/EnumOptionArgument.java 2008-11-16 02:53:07 UTC (rev 4703)
@@ -26,7 +26,7 @@
import org.jnode.driver.console.CompletionInfo;
import org.jnode.shell.help.Argument;
-import org.jnode.shell.help.Help;
+import org.jnode.shell.help.HelpFactory;
import org.jnode.shell.help.Parameter;
import org.jnode.shell.help.ParsedArguments;
@@ -55,7 +55,7 @@
return result.substring(1);
}
- public void describe(Help help, PrintWriter out) {
+ public void describe(HelpFactory help, PrintWriter out) {
for (EnumOption<T> option : options)
option.describe(help, out);
}
Modified: trunk/shell/src/shell/org/jnode/shell/help/argument/OptionArgument.java
===================================================================
--- trunk/shell/src/shell/org/jnode/shell/help/argument/OptionArgument.java 2008-11-12 13:47:18 UTC (rev 4702)
+++ trunk/shell/src/shell/org/jnode/shell/help/argument/OptionArgument.java 2008-11-16 02:53:07 UTC (rev 4703)
@@ -25,7 +25,7 @@
import org.jnode.driver.console.CompletionInfo;
import org.jnode.shell.help.Argument;
-import org.jnode.shell.help.Help;
+import org.jnode.shell.help.HelpFactory;
import org.jnode.shell.help.Parameter;
/**
@@ -54,7 +54,7 @@
}
@Override
- public void describe(Help help, PrintWriter out) {
+ public void describe(HelpFactory help, PrintWriter out) {
for (Option option : options)
option.describe(help, out);
}
Deleted: trunk/shell/src/shell/org/jnode/shell/help/def/DefaultHelp.java
===================================================================
--- trunk/shell/src/shell/org/jnode/shell/help/def/DefaultHelp.java 2008-11-12 13:47:18 UTC (rev 4702)
+++ trunk/shell/src/shell/org/jnode/shell/help/def/DefaultHelp.java 2008-11-16 02:53:07 UTC (rev 4703)
@@ -1,347 +0,0 @@
-/*
- * $Id$
- *
- * JNode.org
- * Copyright (C) 2003-2006 JNode.org
- *
- * This library is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation; either version 2.1 of the License, or
- * (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
- * License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; If not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-package org.jnode.shell.help.def;
-
-import java.io.PrintWriter;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.TreeSet;
-
-import org.jnode.shell.help.Argument;
-import org.jnode.shell.help.Help;
-import org.jnode.shell.help.Parameter;
-import org.jnode.shell.help.Syntax;
-import org.jnode.shell.syntax.ArgumentBundle;
-import org.jnode.shell.syntax.FlagArgument;
-import org.jnode.shell.syntax.OptionSyntax;
-import org.jnode.shell.syntax.SyntaxBundle;
-
-/**
- * @author qades
- * @author Fabien DUMINY (fd...@jn...)
- * @author cr...@jn...
- */
-public class DefaultHelp extends Help {
- public static final String RESOURCE_NAME = "messages.properties";
- private static final int NOMINAL_WIDTH = 75;
- /* start with 80 spaces ... */
- private static String spaces =
- " ";
-
- /**
- * Create a new instance
- */
- public DefaultHelp() {
- }
-
- /**
- * Shows the complete help for a command.
- *
- * @see Help#help(org.jnode.shell.help.Help.Info, String)
- */
- public void help(Info info, String command, PrintWriter out) {
- final Syntax[] syntaxes = info.getSyntaxes();
- final String name = command == null ? info.getName() : command;
- for (int i = 0; i < syntaxes.length; i++) {
- help(name, syntaxes[i], out);
- if (i < syntaxes.length) {
- out.println();
- }
- }
- }
-
- @Override
- public void help(SyntaxBundle syntaxes, ArgumentBundle bundle, PrintWriter out) {
- usage(syntaxes, bundle, out);
- if (bundle.getDescription() != null) {
- out.println("\n" + Help.getLocalizedHelp("help.description") + ":");
- format(out, new Cell[]{new Cell(4, NOMINAL_WIDTH - 4)},
- new String[]{bundle.getDescription()});
- }
- Map<String, TreeSet<String>> flagMap = buildFlagMap(syntaxes);
- boolean first = true;
- for (org.jnode.shell.syntax.Argument<?> arg : bundle) {
- if (arg instanceof FlagArgument) {
- if (first) {
- out.println("\n" + Help.getLocalizedHelp("help.options") + ":");
- first = false;
- }
- describeOption((FlagArgument) arg, flagMap.get(arg.getLabel()), out);
- }
- }
- first = true;
- for (org.jnode.shell.syntax.Argument<?> arg : bundle) {
- if (!(arg instanceof FlagArgument)) {
- if (first) {
- out.println("\n" + Help.getLocalizedHelp("help.parameters") + ":");
- first = false;
- }
- describeArgument(arg, out);
- }
- }
- }
-
- private Map<String, TreeSet<String>> buildFlagMap(SyntaxBundle syntaxes) {
- HashMap<String, TreeSet<String>> res = new HashMap<String, TreeSet<String>>();
- for (org.jnode.shell.syntax.Syntax syntax : syntaxes.getSyntaxes()) {
- buildFlagMap(syntax, res);
- }
- return res;
- }
-
- private void buildFlagMap(org.jnode.shell.syntax.Syntax syntax,
- HashMap<String, TreeSet<String>> res) {
- if (syntax instanceof OptionSyntax) {
- OptionSyntax os = (OptionSyntax) syntax;
- String key = os.getArgName();
- TreeSet<String> options = res.get(key);
- if (options == null) {
- options = new TreeSet<String>();
- res.put(key, options);
- }
- String shortOptName = os.getShortOptName();
- if (shortOptName != null) {
- options.add(shortOptName);
- }
- String longOptName = os.getLongOptName();
- if (longOptName != null) {
- options.add(longOptName);
- }
- } else {
- for (org.jnode.shell.syntax.Syntax child : syntax.getChildren()) {
- buildFlagMap(child, res);
- }
- }
- }
-
- /**
- * Shows the help for a command syntax.
- */
- public void help(String name, Syntax syntax, PrintWriter out) {
- usage(name, syntax, out);
- if (syntax.getDescription() != null) {
- out.println("\n" + Help.getLocalizedHelp("help.description") + ":");
- format(out, new Cell[]{new Cell(4, NOMINAL_WIDTH - 4)},
- new String[]{syntax.getDescription()});
- }
- final Parameter[] params = syntax.getParams();
- if (params.length != 0) {
- out.println("\n" + Help.getLocalizedHelp("help.parameters") + ":");
- for (int i = 0; i < params.length; i++) {
- params[i].describe(this, out);
- }
- }
- }
-
- /**
- * Shows the usage information of a command.
- */
- public void usage(Info info, PrintWriter out) {
- final Syntax[] syntaxes = info.getSyntaxes();
- for (int i = 0; i < syntaxes.length; i++) {
- usage(info.getName(), syntaxes[i], out);
- }
- }
-
- /**
- * Shows the usage information of a command.
- */
- public void usage(String name, Syntax syntax, PrintWriter out) {
- StringBuilder line = new StringBuilder(name);
- final Parameter[] params = syntax.getParams();
- for (int i = 0; i < params.length; i++) {
- line.append(' ').append(params[i].format());
- }
- out.println(Help.getLocalizedHelp("help.usage") + ": " + line);
- }
-
- @Override
- public void usage(SyntaxBundle syntaxBundle, ArgumentBundle bundle, PrintWriter out) {
- String command = syntaxBundle.getAlias();
- String usageText = Help.getLocalizedHelp("help.usage") + ":";
- int usageLength = usageText.length();
- int commandLength = command.length();
- Cell[] cells =
- new Cell[]{new Cell(0, usageLength), new Cell(1, commandLength),
- new Cell(1, NOMINAL_WIDTH - 2 - usageLength - commandLength)};
- String[] texts = new String[]{usageText, command, null};
- String[] texts2 = new String[]{"", "", null};
- org.jnode.shell.syntax.Syntax[] syntaxes = syntaxBundle.getSyntaxes();
- if (syntaxes.length > 0) {
- for (int i = 0; i < syntaxes.length; i++) {
- if (i == 1) {
- texts[0] = getSpaces(usageLength);
- }
- texts[2] = syntaxes[i].format(bundle);
- format(out, cells, texts);
- texts2[2] = syntaxes[i].getDescription();
- format(out, cells, texts2);
- }
- } else {
- texts[2] = "";
- format(out, cells, texts);
- }
- }
-
- public void describeParameter(Parameter param, PrintWriter out) {
- format(out, new Cell[]{new Cell(2, 18), new Cell(2, NOMINAL_WIDTH - 22)},
- new String[]{param.getName(), param.getDescription()});
- }
-
- public void describeArgument(Argument arg, PrintWriter out) {
- format(out, new Cell[]{new Cell(4, 16), new Cell(2, NOMINAL_WIDTH - 22)},
- new String[]{arg.getName(), arg.getDescription()});
- }
-
- @Override
- public void describeArgument(org.jnode.shell.syntax.Argument<?> arg, PrintWriter out) {
- String description = "(" + arg.getTypeDescription() + ") " + arg.getDescription();
- format(out, new Cell[]{new Cell(4, 16), new Cell(2, NOMINAL_WIDTH - 22)},
- new String[]{"<" + arg.getLabel() + ">", description});
- }
-
- @Override
- public void describeOption(FlagArgument arg, TreeSet<String> flagTokens, PrintWriter out) {
- StringBuffer sb = new StringBuffer();
- for (String flagToken : flagTokens) {
- if (sb.length() > 0) {
- sb.append(" | ");
- }
- sb.append(flagToken);
- }
- format(out, new Cell[]{new Cell(4, 16), new Cell(2, NOMINAL_WIDTH - 22)},
- new String[]{sb.toString(), arg.getDescription()});
- }
-
- protected void format(PrintWriter out, Cell[] cells, String[] texts) {
- if (cells.length != texts.length) {
- throw new IllegalArgumentException("Number of cells and texts must match");
- }
- // The text remaining to be formatted for each column.
- String[] remains = new String[texts.length];
- // The total count of characters remaining
- int remainsCount = 0;
- // Initialize 'remains' and 'remainsCount' for the first iteration
- for (int i = 0; i < texts.length; i++) {
- remains[i] = (texts[i] == null) ? "" : texts[i].trim();
- remainsCount += remains[i].length();
- }
-
- StringBuilder result = new StringBuilder();
- // Repeat while there is still text to output.
- while (remainsCount > 0) {
- // Each iteration uses 'fit' to get up to 'cell.width' characters from each column
- // and then uses 'stamp' to append to them to the buffer with the leading margin
- // and trailing padding as required.
- remainsCount = 0;
- for (int i = 0; i < cells.length; i++) {
- String field = cells[i].fit(remains[i]);
- remains[i] = remains[i].substring(field.length());
- remainsCount += remains[i].length();
- result.append(cells[i].stamp(field.trim()));
- }
- result.append('\n');
- }
- out.print(result.toString());
- }
-
- /**
- * Get a String consisting of 'count' spaces.
- *
- * @param count the number of spaces
- * @return the string
- */
- private static String getSpaces(int count) {
- // The following assumes that 1) StringBuilder.append is efficient if you
- // preallocate the StringBuilder, 2) StringBuilder.toString() does no character
- // copying, and 3) String.substring(...) also does no character copying.
- int len = spaces.length();
- if (count > len) {
- StringBuilder sb = new StringBuilder(count);
- for (int i = 0; i < count; i++) {
- sb.append(' ');
- }
- spaces = sb.toString();
- return spaces;
- } else if (count == len) {
- return spaces;
- } else {
- return spaces.substring(0, count);
- }
- }
-
- /**
- * A Cell is a template for formatting text for help messages. (It is 'protected' so that
- * the unit test can declare a subclass ...)
- */
- protected static class Cell {
-
- final String field;
- final int margin;
- final int width;
-
- /**
- * Construct a Cell with a leading margin and a text width.
- *
- * @param margin the number of leading spaces for the Cell
- * @param width the width of the text part of the Cell
- */
- protected Cell(int margin, int width) {
- this.margin = margin;
- this.width = width;
-
- // for performance, we pre-build the field mask
- this.field = getSpaces(margin + width);
- }
-
- /**
- * Heuristically, split of a head substring of 'text' to fit within this Cell's width. We try
- * to split at a space character, but if this will make the text too ragged, we simply chop.
- */
- protected String fit(String text) {
- if (width >= text.length()) {
- return text;
- }
- String hardFit = text.substring(0, width);
- if (hardFit.endsWith(" ")) {
- return hardFit;
- }
- int lastSpace = hardFit.lastIndexOf(' ');
- if (lastSpace > 3 * width / 4) {
- return hardFit.substring(0, lastSpace);
- } else {
- return hardFit;
- }
- }
-
- /**
- * Stamp out a line with leading and trailing spaces to fill the Cell.
- */
- protected String stamp(String text) {
- if (text.length() > field.length())
- throw new IllegalArgumentException("Text length exceeds field width");
- return field.substring(0, margin) + text + field.substring(0, width - text.length());
- }
- }
-
-
-}
Added: trunk/shell/src/shell/org/jnode/shell/help/def/DefaultHelpFactory.java
===================================================================
--- trunk/shell/src/shell/org/jnode/shell/help/def/DefaultHelpFactory.java (rev 0)
+++ trunk/shell/src/shell/org/jnode/shell/help/def/DefaultHelpFactory.java 2008-11-16 02:53:07 UTC (rev 4703)
@@ -0,0 +1,387 @@
+/*
+ * $Id: DefaultHelp.java 4556 2008-09-13 08:02:20Z crawley $
+ *
+ * JNode.org
+ * Copyright (C) 2003-2006 JNode.org
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; If not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+package org.jnode.shell.help.def;
+
+import java.io.PrintWriter;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.TreeSet;
+
+import org.jnode.shell.Command;
+import org.jnode.shell.CommandInfo;
+import org.jnode.shell.Shell;
+import org.jnode.shell.ShellUtils;
+import org.jnode.shell.help.Argument;
+import org.jnode.shell.help.Help;
+import org.jnode.shell.help.HelpException;
+import org.jnode.shell.help.HelpFactory;
+import org.jnode.shell.help.Parameter;
+import org.jnode.shell.help.Syntax;
+import org.jnode.shell.syntax.ArgumentBundle;
+import org.jnode.shell.syntax.FlagArgument;
+import org.jnode.shell.syntax.OptionSyntax;
+import org.jnode.shell.syntax.SyntaxBundle;
+import org.jnode.shell.syntax.SyntaxManager;
+
+/**
+ * @author qades
+ * @author Fabien DUMINY (fd...@jn...)
+ * @author cr...@jn...
+ */
+public class DefaultHelpFactory extends HelpFactory {
+ public static final String RESOURCE_NAME = "messages.properties";
+ private static final int NOMINAL_WIDTH = 75;
+ /* start with 80 spaces ... */
+ private static String spaces =
+ " ";
+
+ /**
+ * Create a new instance
+ */
+ public DefaultHelpFactory() {
+ }
+
+ @Override
+ public Help getHelp(String alias, CommandInfo cmdInfo) throws HelpException {
+ Help.Info info = null;
+ SyntaxBundle syntaxes = null;
+ ArgumentBundle bundle = null;
+ try {
+ final Shell shell = ShellUtils.getShellManager().getCurrentShell();
+ final SyntaxManager syntaxManager = shell.getSyntaxManager();
+ Class<?> clazz = cmdInfo.getCommandClass();
+ Command cmd = cmdInfo.createCommandInstance();
+ if (cmd != null) {
+ bundle = cmd.getArgumentBundle();
+ syntaxes = syntaxManager.getSyntaxBundle(alias);
+ if (syntaxes == null) {
+ syntaxes = new SyntaxBundle(alias, bundle.createDefaultSyntax());
+ }
+ } else {
+ info = HelpFactory.getInfo(clazz);
+ }
+ } catch (HelpException ex) {
+ throw ex;
+ } catch (Exception ex) {
+ throw new HelpException(ex.getMessage(), ex);
+ }
+
+ if (info != null && alias != null) {
+ return new OldSyntaxHelp(info, alias);
+ } else if (syntaxes != null && bundle != null) {
+ return new NewSyntaxHelp(syntaxes, bundle);
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Shows the complete help for a command.
+ *
+ * @see HelpFactory#help(org.jnode.shell.help.HelpFactory.Info, String)
+ */
+ public void help(Help.Info info, String command, PrintWriter out) {
+ final Syntax[] syntaxes = info.getSyntaxes();
+ final String name = command == null ? info.getName() : command;
+ for (int i = 0; i < syntaxes.length; i++) {
+ help(name, syntaxes[i], out);
+ if (i < syntaxes.length) {
+ out.println();
+ }
+ }
+ }
+
+ @Override
+ public void help(SyntaxBundle syntaxes, ArgumentBundle bundle, PrintWriter out) {
+ usage(syntaxes, bundle, out);
+ if (bundle.getDescription() != null) {
+ out.println("\n" + HelpFactory.getLocalizedHelp("help.description") + ":");
+ format(out, new Cell[]{new Cell(4, NOMINAL_WIDTH - 4)},
+ new String[]{bundle.getDescription()});
+ }
+ Map<String, TreeSet<String>> flagMap = buildFlagMap(syntaxes);
+ boolean first = true;
+ for (org.jnode.shell.syntax.Argument<?> arg : bundle) {
+ if (arg instanceof FlagArgument) {
+ if (first) {
+ out.println("\n" + HelpFactory.getLocalizedHelp("help.options") + ":");
+ first = false;
+ }
+ describeOption((FlagArgument) arg, flagMap.get(arg.getLabel()), out);
+ }
+ }
+ first = true;
+ for (org.jnode.shell.syntax.Argument<?> arg : bundle) {
+ if (!(arg instanceof FlagArgument)) {
+ if (first) {
+ out.println("\n" + HelpFactory.getLocalizedHelp("help.parameters") + ":");
+ first = false;
+ }
+ describeArgument(arg, out);
+ }
+ }
+ }
+
+ private Map<String, TreeSet<String>> buildFlagMap(SyntaxBundle syntaxes) {
+ HashMap<String, TreeSet<String>> res = new HashMap<String, TreeSet<String>>();
+ for (org.jnode.shell.syntax.Syntax syntax : syntaxes.getSyntaxes()) {
+ buildFlagMap(syntax, res);
+ }
+ return res;
+ }
+
+ private void buildFlagMap(org.jnode.shell.syntax.Syntax syntax,
+ HashMap<String, TreeSet<String>> res) {
+ if (syntax instanceof OptionSyntax) {
+ OptionSyntax os = (OptionSyntax) syntax;
+ String key = os.getArgName();
+ TreeSet<String> options = res.get(key);
+ if (options == null) {
+ options = new TreeSet<String>();
+ res.put(key, options);
+ }
+ String shortOptName = os.getShortOptName();
+ if (shortOptName != null) {
+ options.add(shortOptName);
+ }
+ String longOptName = os.getLongOptName();
+ if (longOptName != null) {
+ options.add(longOptName);
+ }
+ } else {
+ for (org.jnode.shell.syntax.Syntax child : syntax.getChildren()) {
+ buildFlagMap(child, res);
+ }
+ }
+ }
+
+ /**
+ * Shows the help for a command syntax.
+ */
+ public void help(String name, Syntax syntax, PrintWriter out) {
+ usage(name, syntax, out);
+ if (syntax.getDescription() != null) {
+ out.println("\n" + HelpFactory.getLocalizedHelp("help.description") + ":");
+ format(out, new Cell[]{new Cell(4, NOMINAL_WIDTH - 4)},
+ new String[]{syntax.getDescription()});
+ }
+ final Parameter[] params = syntax.getParams();
+ if (params.length != 0) {
+ out.println("\n" + HelpFactory.getLocalizedHelp("help.parameters") + ":");
+ for (int i = 0; i < params.length; i++) {
+ params[i].describe(this, out);
+ }
+ }
+ }
+
+ /**
+ * Shows the usage information of a command.
+ */
+ public void usage(Help.Info info, PrintWriter out) {
+ final Syntax[] syntaxes = info.getSyntaxes();
+ for (int i = 0; i < syntaxes.length; i++) {
+ usage(info.getName(), syntaxes[i], out);
+ }
+ }
+
+ /**
+ * Shows the usage information of a command.
+ */
+ public void usage(String name, Syntax syntax, PrintWriter out) {
+ StringBuilder line = new StringBuilder(name);
+ final Parameter[] params = syntax.getParams();
+ for (int i = 0; i < params.length; i++) {
+ line.append(' ').append(params[i].format());
+ }
+ out.println(HelpFactory.getLocalizedHelp("help.usage") + ": " + line);
+ }
+
+ @Override
+ public void usage(SyntaxBundle syntaxBundle, ArgumentBundle bundle, PrintWriter out) {
+ String command = syntaxBundle.getAlias();
+ String usageText = HelpFactory.getLocalizedHelp("help.usage") + ":";
+ int usageLength = usageText.length();
+ int commandLength = command.length();
+ Cell[] cells =
+ new Cell[]{new Cell(0, usageLength), new Cell(1, commandLength),
+ new Cell(1, NOMINAL_WIDTH - 2 - usageLength - commandLength)};
+ String[] texts = new String[]{usageText, command, null};
+ String[] texts2 = new String[]{"", "", null};
+ org.jnode.shell.syntax.Syntax[] syntaxes = syntaxBundle.getSyntaxes();
+ if (syntaxes.length > 0) {
+ for (int i = 0; i < syntaxes.length; i++) {
+ if (i == 1) {
+ texts[0] = getSpaces(usageLength);
+ }
+ texts[2] = syntaxes[i].format(bundle);
+ format(out, cells, texts);
+ texts2[2] = syntaxes[i].getDescription();
+ format(out, cells, texts2);
+ }
+ } else {
+ texts[2] = "";
+ format(out, cells, texts);
+ }
+ }
+
+ public void describeParameter(Parameter param, PrintWriter out) {
+ format(out, new Cell[]{new Cell(2, 18), new Cell(2, NOMINAL_WIDTH - 22)},
+ new String[]{param.getName(), param.getDescription()});
+ }
+
+ public void describeArgument(Argument arg, PrintWriter out) {
+ format(out, new Cell[]{new Cell(4, 16), new Cell(2, NOMINAL_WIDTH - 22)},
+ new String[]{arg.getName(), arg.getDescription()});
+ }
+
+ @Override
+ public void describeArgument(org.jnode.shell.syntax.Argument<?> arg, PrintWriter out) {
+ String description = "(" + arg.getTypeDescription() + ") " + arg.getDescription();
+ format(out, new Cell[]{new Cell(4, 16), new Cell(2, NOMINAL_WIDTH - 22)},
+ new String[]{"<" + arg.getLabel() + ">", description});
+ }
+
+ @Override
+ public void describeOption(FlagArgument arg, TreeSet<String> flagTokens, PrintWriter out) {
+ StringBuffer sb = new StringBuffer();
+ for (String flagToken : flagTokens) {
+ if (sb.length() > 0) {
+ sb.append(" | ");
+ }
+ sb.append(flagToken);
+ }
+ format(out, new Cell[]{new Cell(4, 16), new Cell(2, NOMINAL_WIDTH - 22)},
+ new String[]{sb.toString(), arg.getDescription()});
+ }
+
+ protected void format(PrintWriter out, Cell[] cells, String[] texts) {
+ if (cells.length != texts.length) {
+ throw new IllegalArgumentException("Number of cells and texts must match");
+ }
+ // The text remaining to be formatted for each column.
+ String[] remains = new String[texts.length];
+ // The total count of characters remaining
+ int remainsCount = 0;
+ // Initialize 'remains' and 'remainsCount' for the first iteration
+ for (int i = 0; i < texts.length; i++) {
+ remains[i] = (texts[i] == null) ? "" : texts[i].trim();
+ remainsCount += remains[i].length();
+ }
+
+ StringBuilder result = new StringBuilder();
+ // Repeat while there is still text to output.
+ while (remainsCount > 0) {
+ // Each iteration uses 'fit' to get up to 'cell.width' characters from each column
+ // and then uses 'stamp' to append to them to the buffer with the leading margin
+ // and trailing padding as required.
+ remainsCount = 0;
+ for (int i = 0; i < cells.length; i++) {
+ String field = cells[i].fit(remains[i]);
+ remains[i] = remains[i].substring(field.length());
+ remainsCount += remains[i].length();
+ result.append(cells[i].stamp(field.trim()));
+ }
+ result.append('\n');
+ }
+ out.print(result.toString());
+ }
+
+ /**
+ * Get a String consisting of 'count' spaces.
+ *
+ * @param count the number of spaces
+ * @return the string
+ */
+ private static String getSpaces(int count) {
+ // The following assumes that 1) StringBuilder.append is efficient if you
+ // preallocate the StringBuilder, 2) StringBuilder.toString() does no character
+ // copying, and 3) String.substring(...) also does no character copying.
+ int len = spaces.length();
+ if (count > len) {
+ StringBuilder sb = new StringBuilder(count);
+ for (int i = 0; i < count; i++) {
+ sb.append(' ');
+ }
+ spaces = sb.toString();
+ return spaces;
+ } else if (count == len) {
+ return spaces;
+ } else {
+ return spaces.substring(0, count);
+ }
+ }
+
+ /**
+ * A Cell is a template for formatting text for help messages. (It is 'protected' so that
+ * the unit test can declare a subclass ...)
+ */
+ protected static class Cell {
+
+ final Str...
[truncated message content] |