using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.Specialized;
using Yaulw.Tools;
namespace Yaulw.Other
{
///
/// CommandLine Arguments Parser for an Application
///
///
/// internal CMDline cmdline = new CMDline(typeof(App.CommandLine_Option), typeof(App.CommandLine_Flag));
///
/// public enum CommandLine_Flag
/// {
/// START,
/// STOP,
/// SHOW,
/// }
///
/// public enum CommandLine_Option
/// {
/// ADD_SOMETHING,
/// REMOVE_SOMETHING,
/// }
///
/// cmdline.Parse(e.Args);
///
/// if (cmdline.HasParams)
/// {
/// if (App.cmdline.ShowHelp || !App.cmdline.ParamsValid)
/// {
/// ShowCommandLineHelp();
/// return;
/// }
///
/// string AddSomething = cmdline.GetOptionValue(CommandLine_Option.ADD_SOMETHING, ""); //
/// }
///
///
///
public class CMDline
{
#region private Variables
// Flag or Option Specifiers CONSTS
private const String FLAG_OR_OPTION_SPECIFIER = "-/";
private const String HELP_FLAG_SPECIFIER = "?";
// Private Parsing Enums
private Type _CMDLineOptions = null;
private Type _CMDLineFlags = null;
// Private Parsing Data Structures
private Stack _stringStack = new Stack();
private StringDictionary _stringDictionary = new StringDictionary();
// Keep track of the last parsed args as an array
private string[] _lastparsedArgs = null;
#endregion
#region Construction
///
/// The Command Line Class needs to know what Options and Flags to Parse for
///
/// Pass an Enum used to determine CommandLine Options
/// Pass an Enum used to determine CommandLine Flags
public CMDline(Type Enum_CMDLineOptions, Type Enum_CMDLineFlags)
{
if (Enum_CMDLineOptions.IsEnum && Enum_CMDLineFlags.IsEnum)
{
_CMDLineOptions = Enum_CMDLineOptions;
_CMDLineFlags = Enum_CMDLineFlags;
}
else
throw new ArgumentException("Both CMDLineOptions and CMDLineFlags must be Enums");
}
#endregion
#region Public Properties
///
/// True if User Passed in any Parameters
///
public bool HasParams { get { return (_stringDictionary.Count >= 1); } }
///
/// True if User requested Command-Line Help
///
public bool ShowHelp { get { return GetFlagOrOptionValueBool(HELP_FLAG_SPECIFIER); } }
///
/// True if all Parameters parsed are valid, False otherwise
///
public bool ParamsValid
{
get
{
if (!HasParams)
return true;
string[] OptionNames = Enum.GetNames(_CMDLineOptions);
string[] FlagNames = Enum.GetNames(_CMDLineFlags);
// Get All Flags and Options
List AllFlagsAndOptions = new List();
foreach (string Option in OptionNames)
AllFlagsAndOptions.Add(Option.ToLower());
foreach (string Flag in FlagNames)
AllFlagsAndOptions.Add(Flag.ToLower());
// Verify the Parameters
bool InvalidParamFound = false;
foreach (string key in _stringDictionary.Keys)
{
InvalidParamFound = (key != HELP_FLAG_SPECIFIER) && !AllFlagsAndOptions.Contains(key);
if (InvalidParamFound)
break;
}
return !InvalidParamFound;
}
}
#endregion
#region Public Methods
///
/// Main Entry Function to Retrieve an Option Value
///
/// Should be a System Type like string, bool, int32, double, decimal, etc...
/// option to retrieve (From CMDLineOptions Enum)
/// Default value to use if nothing was retrieved * Error occured *
/// value or default value, if not found
public T GetOptionValue(Enum option, T DefaultValue)
{
T RetVal = DefaultValue;
string StringVal = GetFlagOrOptionValueStr(option.ToString());
try
{
if (ObjTool.IsNotNullAndNotEmpty(StringVal))
{
RetVal = ObjTool.ConvertStringToObj(StringVal);
}
}
catch (Exception) { /* ignore */ }
return RetVal;
}
///
/// Main Entry Function to Retrieve a Flag Value
///
/// flag enum to retrieve (From CMDLineFlags Enum)
/// Bool Value found or false if not found
public bool GetFlagValue(Enum flag)
{
return GetFlagOrOptionValueBool(flag.ToString());
}
///
/// Returns the Last Parsed Arguments as a string
///
/// returns last parsed args or String.Empty if none
public string ParsedArgs()
{
if (_lastparsedArgs != null && _lastparsedArgs.Length > 0)
{
StringBuilder sb = new StringBuilder();
foreach (string s in _lastparsedArgs)
{
sb.Append(s);
sb.Append(" ");
}
sb.Remove(sb.Length - 1, 1); // remove trailing " "
return sb.ToString();
}
return string.Empty;
}
#endregion
#region Private Helper Functions
///
/// Main Function used to Retrieve a String Value
///
/// Flag or Option to get Value for
/// Value or Empty if not found
private string GetFlagOrOptionValueStr(string FlagOrOption)
{
// If there is a FLAG_OR_OPTION_CHARS, stripe it
if (IsFlagOrOption(FlagOrOption))
FlagOrOption = GetFlagOrOption(FlagOrOption);
FlagOrOption = FlagOrOption.ToLower();
if (_stringDictionary.ContainsKey(FlagOrOption))
return _stringDictionary[FlagOrOption];
return String.Empty;
}
///
/// Main Function used to Retrieve a Bool Value
///
/// Flag or Option to get Value for
/// True or False if not found
private bool GetFlagOrOptionValueBool(string FlagOrOption)
{
try
{
string Value = GetFlagOrOptionValueStr(FlagOrOption);
if (!String.IsNullOrEmpty(Value))
{
bool bValue = bool.Parse(Value);
return bValue;
}
}
catch (Exception) { /*Ignore*/ }
return false;
}
#endregion
#region Parsing Methods
/// true if the param is a flag or option
private bool IsFlagOrOption(string arg)
{
return (FLAG_OR_OPTION_SPECIFIER.Contains(arg[0].ToString()));
}
/// the Value of a Param
private string GetFlagOrOption(string arg)
{
return arg.Substring(1);
}
///
/// Main Entry Function used to Parse CommandLine parameters
///
/// command line arguments
/// true if any parsing occured, false otherwise
public bool Parse(string[] args)
{
return Parse(args, true);
}
///
/// Main Entry Function used to Parse CommandLine parameters
///
/// command line arguments
/// Allows you to not parse Options as True, if in case the option is blank it will just be considered a blank option/flag
/// true if any parsing occured, false otherwise
public bool Parse(string[] args, bool bAlwaysParseOptionsAsTrue)
{
if (args == null || args.Length <= 0)
return false;
_stringDictionary.Clear();
_stringStack.Clear();
_lastparsedArgs = args;
foreach (string arg in args)
{
if (!String.IsNullOrEmpty(arg))
{
if (IsFlagOrOption(arg))
{
_stringStack.Push(GetFlagOrOption(arg).ToLower());
if (bAlwaysParseOptionsAsTrue)
_stringDictionary[GetFlagOrOption(arg).ToLower()] = "TRUE";
}
else
{
// must have a flag or option on the stack,
// if it does we use it
if (_stringStack.Count >= 1)
{
_stringDictionary[_stringStack.Pop()] = Parse_ArgCleanup(arg);
}
}
}
}
_stringStack.Clear();
return true;
}
///
/// Used only when cmd is constructed with (null, null),
/// and the cmd.Parse function is called. will iterate thru the internal
/// dictionary and stack and make sure that the command string / line items
/// are valid
///
///
public string MakeValidCmdStrFromNewlyParsedCmdLine()
{
StringBuilder sb = new StringBuilder();
foreach (string key in _stringDictionary.Keys)
{
sb.Append(FLAG_OR_OPTION_SPECIFIER[0]);
sb.Append(MakeValidCmdStr(key));
sb.Append("=");
sb.Append(_stringDictionary[key]);
sb.Append("");
}
foreach (string flag in _stringStack)
{
sb.Append(FLAG_OR_OPTION_SPECIFIER[0]);
sb.Append(MakeValidCmdStr(flag));
sb.Append("");
}
// remove trailing space
sb = sb.Remove(sb.Length - 1, 1);
return sb.ToString();
}
///
/// It appears that the Command-Line can foul us up sometimes when passing
/// certain arguments. This function deals with these special cases.
///
/// arg to check/poss.clean up
/// cleaned up arg, if needed
private string Parse_ArgCleanup(string arg)
{
if (!String.IsNullOrEmpty(arg) &&
(arg.Length > 2) &&
(arg[arg.Length - 1] == '"')) // when passing a \ at the end of the command-line with a "
{
arg = arg.Remove(arg.Length - 1);
arg += "\\";
}
return arg;
}
#endregion
#region Static Generate CmdLine Method
///
/// Generates a CommandLine Parameter String from the Options/Flags Given
///
/// StringDictionary that contains all the Options, to use
/// List that contains all the Flags to use
/// a string that can be passed via the commandLine
public static string GenerateCmdLine(StringDictionary Options, List Flags)
{
string CmdLine = String.Empty;
// Iterate Options, and add them
if (Options != null && Options.Count > 0)
{
foreach (string Key in Options.Keys)
{
string cmdKey = MakeValidCmdStr(Key);
string cmdValue = Options[Key];
CmdLine = CmdLine + FLAG_OR_OPTION_SPECIFIER[0] + cmdKey + " " + "\"" + cmdValue + "\"" + " ";
}
}
// Iterate Flags, and add them
if (Flags != null && Flags.Count > 0)
{
foreach (string Flag in Flags)
{
string cmdFlag = MakeValidCmdStr(Flag);
CmdLine = CmdLine + FLAG_OR_OPTION_SPECIFIER[0] + cmdFlag + " ";
}
}
// Return the generated Commmand Line
return CmdLine;
}
///
/// Ensures Integrity with the Generated CMDLine string that Keys don't
/// contain Illegal Characters
///
/// a Key to make sure it is valid
/// a valid Key
private static string MakeValidCmdStr(string Key)
{
if (!String.IsNullOrEmpty(Key))
{
//":\\ _!@#$%^&()-+{}[],.;`~";
Key = Key.Replace(" ", "_");
Key = Key.Replace(":", "_");
Key = Key.Replace("\\", "_");
Key = Key.Replace("/", "_");
Key = Key.Replace("!", "_");
Key = Key.Replace("@", "_");
Key = Key.Replace("#", "_");
Key = Key.Replace("$", "_");
Key = Key.Replace("%", "_");
Key = Key.Replace("^", "_");
Key = Key.Replace("&", "_");
Key = Key.Replace("(", "_");
Key = Key.Replace(")", "_");
Key = Key.Replace("-", "_");
Key = Key.Replace("+", "_");
Key = Key.Replace("{", "_");
Key = Key.Replace("}", "_");
Key = Key.Replace("[", "_");
Key = Key.Replace("]", "_");
Key = Key.Replace(",", "_");
Key = Key.Replace(".", "_");
Key = Key.Replace(";", "_");
Key = Key.Replace("'", "_");
Key = Key.Replace("~", "_");
return Key;
}
return String.Empty;
}
#endregion
}
}