//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
// PLEASE DO NOT EDIT WITHOUT THE EXPLICIT CONSENT OF THE AUTHOR! \\
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
using System;
using System.Collections;
namespace Ilog.Language.Tools
{
/**
* This class implements a simple UNIX style command parser. It is meant to
* be subclassed or used directly through its static methods (which is why it
* has no constructor). Its method parseCommandLine(String[]) takes
* the array of strings on command line (i.e., the argument of a
* main method) and determines which options are used with what
* values. It also defines a few utilities (1) to set and access the values of
* the options and arguments specified in the parsed command, (2) to determine
* if these are present, and (3) to do simple file name completion.
*
* @version Last modified on Sun May 22 20:37:28 2005 by hak
* @author Hassan Aït-Kaci
* @copyright © 2000 ILOG, S.A.
*/
public class Command
{
/**
* Options storage.
*/
private static Hashtable optionTable = new Hashtable();
/**
* Command arguments.
*/
private static String[] arguments = null;
/**
* Default argument.
*/
private static String defaultArgument = null;
/**
* The widest length of option names.
*/
private static int optionWidth = " Option".Length;
/**
* The widest length of option defaults.
*/
private static int defaultWidth = "(Default)".Length;
/**
* Sets the default argument to the specified string.
*
* @param arg value to use if the command argument is missing
*/
public static void OptionalArgument (String arg)
{
defaultArgument = arg;
}
/**
* Used locally to check whether the specified option is legal.
* If this option shares a prefix with one already defined,
* a CommandLineException is reported.
*/
private static void CheckOption (String option)
{
foreach (DictionaryEntry entry in optionTable)
{
String name = (String)entry.Key;
if (name.StartsWith(option) || option.StartsWith(name))
throw new CommandLineException
("option '"+option+"' conflicts with option '"+name+"'");
}
}
/**
* Defines an option with a default value.
*
* @param option the option string
* @param defaultValue the option's default
*/
public static void DefineOption (String option, String defaultValue)
{
CheckOption(option);
optionTable[option] = new OptionData(defaultValue);
optionWidth = Math.Max(optionWidth,option.Length+2);
defaultWidth = Math.Max(defaultWidth,defaultValue.Length+3);
}
/**
* Defines an option with a default value and description.
*
* @param option the option string
* @param defaultValue the option's default
* @param help option's description
*/
public static void DefineOption (String option, String defaultValue, String help)
{
CheckOption(option);
optionTable[option] = new OptionData(defaultValue,help);
optionWidth = Math.Max(optionWidth,option.Length+2);
defaultWidth = Math.Max(defaultWidth,defaultValue.Length+3);
}
/**
* Returns the value associated with an option. If the option is
* undefined, a CommandLineException is reported.
*
* @param option the option
*/
public static String GetOption (String option)
{
OptionData data = (OptionData)optionTable[option];
if (data == null)
throw new CommandLineException("unknown command option ("+option+")");
if (data.info == null)
return data.defaultInfo;
return data.info;
}
/**
* Returns true iff the option is actually present on the command line.
* If the option is undefined, a CommandLineException
* is reported.
*
* @param option the option
*/
public static bool OptionIsPresent (String option)
{
OptionData data =(OptionData)optionTable[option];
if (data == null)
throw new CommandLineException("unknown command option ("+option+")");
return (data.info != null);
}
/**
* Returns the info of the argument. If none is specified, returns the
* default argument. If many are specified, the first is returned.
*/
public static String GetArgument ()
{
if (arguments == null)
return defaultArgument;
return arguments[0];
}
/**
* Returns the array of infos of all the arguments. If none is specified,
* returns a one element array containing the default argument.
*/
public static String[] GetArguments ()
{
if (arguments == null)
{
String[] a = new String[] {defaultArgument};
return a;
}
return arguments;
}
/**
* This is true iff an argument is actually present on the command line.
*/
public static bool ArgumentIsPresent
{
get { return arguments != null; }
}
/**
* Returns a file's name without its extension, but including its directory path.
*
* @param name the file's name
*/
public static String FullFileNamePrefix (String name)
{
return FileTools.FullPrefix(name);
}
/**
* Returns a file's name without its extension nor its directory path.
*
* @param name the file's name
*/
public static String FileNamePrefix (String name)
{
return FileTools.Prefix(name);
}
/**
* Returns a file's name's directory part.
*
* @param name the file's name
*/
public static String FileNameDir (String name)
{
return FileTools.Dir(name);
}
/**
* Returns a file's name extension.
*
* @param name the file's name
*/
public static String FileNameSuffix (String name)
{
return FileTools.Suffix(name);
}
/**
* Returns a file's name completed with its extension if the latter
* is missing.
*
* @param name the file's name
* @param ext the file's extension
*/
public static String CompleteFileName (String name, String ext)
{
String suffix = "."+ext;
if (name.EndsWith(suffix))
return name;
return name+suffix;
}
/**
* Prints an item on a given maximum field width.
*/
private static void PadWrite (String item, int width)
{
Console.Write(item.PadRight(width));
}
/**
* Prints a line description of an option.
*/
private static void PrintHelpLine (String option, String info, String description)
{
PadWrite(option,optionWidth);
PadWrite(info,defaultWidth);
Console.WriteLine(description);
}
private static String usage = null;
public static String GetUsage ()
{
return usage;
}
public static void SetUsage (String usg)
{
usage = usg;
}
public static void PrintUsage ()
{
if (usage != null)
Console.WriteLine(usage);
}
/**
* Prints a listing of known options, their defaults, and descriptions.
*/
public static void PrintHelp ()
{
PrintUsage();
if (optionTable.Count == 0)
Console.WriteLine("Sorry - no help available!");
else
{
PrintHelpLine("Option ","(Default)","Description");
PrintHelpLine("------ ","---------","-----------");
foreach (DictionaryEntry entry in optionTable)
{
OptionData data = (OptionData)entry.Value;
PrintHelpLine("-"+entry.Key,"("+data.defaultInfo+")",data.help);
}
Console.WriteLine();
}
}
/**
* Parses the command line recognizing the defined options and the
* arguments, and storing their specified infos as appropriate.
* Note that if the same option is specified more than once on the
* command line, only the last one is effective.
*/
public static bool ParseCommandLine (String[] args)
{
OptionData data = null;
int i = 0;
while (i < args.Length) // as long as there are arguments
{
if (args[i][0] == '-') // if this argument starts with '-', it is an option
{
bool known = false; // a flag to indicate that this option is known
bool hasInfo = false; // a flag to indicate that this option is "stuck" to its info
args[i] = args[i].Substring(1); // keep what follows the '-'
int full = args[i].Length; // the full length of the argument
if (full > 0) // if there is something after the '-'
foreach (DictionaryEntry entry in optionTable) // for all known options
{
String option = (String)entry.Key; // let option be the next known option
data = (OptionData)entry.Value; // and let data be its value
if (args[i].StartsWith(option)) // if it matches the start of this argument
{
int part = option.Length; // let part be the length of the option name
if (hasInfo = (part < full))// the option has info if shorter than the argument
data.info = args[i].Substring(part,full-part); // the info is the arg's tail
known = true; // remember that we found this option
break; // no need to look further.
}
}
if (!known) // this is not a known option
{
Console.WriteLine("-{0} is not a known option!",args[i]);
PrintHelp(); // tell what options are known
return false; // the parsing fails
}
if (hasInfo) // this is a known option and its info is part of it
{
i++; // proceed to the next argument
continue;
}
// is there a info for this option?
if (i < args.Length-1) // if there are more arguments
{
if (args[i+1][0] != '-') // if the next argument arg is not an option
if (data.defaultInfo.Length > 0) // it's the the previous option's info
{
data.info = args[i+1]; // take this value as that info
i += 2; // and skip this value
continue;
}
}
if (data.info == null && data.defaultInfo.Length == 0)
// this option does not need a info
data.info = ""; // so just record it as present
i++;
}
else
{
arguments = new String[args.Length-i];
Array.Copy(args,i,arguments,0,args.Length-i);
break;
}
}
return true; // the parse succeeds!
}
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
/**
* This defines a structure gathering information about an an option.
* An instance of this structure will be stored in the hashtable of options.
*/
private class OptionData
{
/**
* Info of the option specified on the command line.
*/
internal String info;
/**
* Info to use if none is specified for this option.
*/
internal String defaultInfo;
/**
* Some description of the purpose of this option.
*/
internal String help = "";
/**
* Constructs an OptionData with the specified default info.
*
* @param defaultInfo option's default
*/
internal OptionData (String defaultInfo)
{
this.defaultInfo = defaultInfo;
}
/**
* Constructs an OptionData with the specified default info,
* and some description for help.
*
* @param defaultInfo option's default
* @param help option's description
*/
internal OptionData (String defaultInfo, String help)
{
this.defaultInfo = defaultInfo;
this.help = help;
}
}
}
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
/**
* Signals an anomalous situation while parsing a command line.
*/
public class CommandLineException : ApplicationException
{
/**
* Constructs a new CommandLineException with a message.
*/
internal CommandLineException (String msg)
: base("*** Command Line Exception: "+msg) {}
}
}