// Source: http://jake.ginnivan.net/c-sharp-argument-parser/ (which is based on http://www.codeproject.com/Articles/3111/C-NET-Command-Line-Arguments-Parser , MIT License) // Removed support for array arguments since snap2html does not need it, and it throws if you try adding a path with comma /* Examples: Argument: –flag Usage: args.IsTrue("flag"); Result: true Argument: –arg:MyValue //Usage: args.Single("arg"); Result: MyValue Argument: –arg "My Value" Usage: args.Single("arg"); Result: ‘My Value’ Argument: /arg=Value /arg=Value2 Usage: args["arg"] Result: new string[] {"Value", "Value2"} Argument: /arg="Value,Value2" Usage: args["arg"] Result: new string[] {"Value", "Value2"} */ using System; using System.Collections.Generic; using System.Text; using System.Collections.ObjectModel; using System.Text.RegularExpressions; namespace CommandLine.Utility { /// <summary> /// Arguments class /// </summary> class Arguments { /// <summary> /// Splits the command line. When main(string[] args) is used escaped quotes (ie a path "c:\folder\") /// Will consume all the following command line arguments as the one argument. /// This function ignores escaped quotes making handling paths much easier. /// </summary> /// <param name="commandLine">The command line.</param> /// <returns></returns> public static string[] SplitCommandLine(string commandLine) { var translatedArguments = new StringBuilder(commandLine); var escaped = false; for (var i = 0; i < translatedArguments.Length; i++) { if (translatedArguments[i] == '"') { escaped = !escaped; } if (translatedArguments[i] == ' ' && !escaped) { translatedArguments[i] = '\n'; } } var toReturn = translatedArguments.ToString().Split(new[] { '\n' }, StringSplitOptions.RemoveEmptyEntries); for (var i = 0; i < toReturn.Length; i++) { toReturn[i] = RemoveMatchingQuotes(toReturn[i]); } return toReturn; } public static string RemoveMatchingQuotes(string stringToTrim) { var firstQuoteIndex = stringToTrim.IndexOf('"'); var lastQuoteIndex = stringToTrim.LastIndexOf('"'); while (firstQuoteIndex != lastQuoteIndex) { stringToTrim = stringToTrim.Remove(firstQuoteIndex, 1); stringToTrim = stringToTrim.Remove(lastQuoteIndex - 1, 1); //-1 because we've shifted the indicies left by one firstQuoteIndex = stringToTrim.IndexOf('"'); lastQuoteIndex = stringToTrim.LastIndexOf('"'); } return stringToTrim; } private readonly Dictionary<string, Collection<string>> _parameters; private string _waitingParameter; public Arguments(IEnumerable<string> arguments) { _parameters = new Dictionary<string, Collection<string>>(); string[] parts; //Splits on beginning of arguments ( - and -- and / ) //And on assignment operators ( = and : ) var argumentSplitter = new Regex(@"^-{1,2}|^/|=|:", RegexOptions.IgnoreCase | RegexOptions.Compiled); foreach (var argument in arguments) { parts = argumentSplitter.Split(argument, 3); switch (parts.Length) { case 1: AddValueToWaitingArgument(parts[0]); break; case 2: AddWaitingArgumentAsFlag(); //Because of the split index 0 will be a empty string _waitingParameter = parts[1]; break; case 3: AddWaitingArgumentAsFlag(); //Because of the split index 0 will be a empty string string valuesWithoutQuotes = RemoveMatchingQuotes(parts[2]); // MOD: Don't split on commas //AddListValues(parts[1], valuesWithoutQuotes.Split(',')); Add( parts[1], valuesWithoutQuotes ); break; } } AddWaitingArgumentAsFlag(); } private void AddListValues(string argument, IEnumerable<string> values) { foreach (var listValue in values) { Add(argument, listValue); } } private void AddWaitingArgumentAsFlag() { if (_waitingParameter == null) return; AddSingle(_waitingParameter, "true"); _waitingParameter = null; } private void AddValueToWaitingArgument(string value) { if (_waitingParameter == null) return; value = RemoveMatchingQuotes(value); Add(_waitingParameter, value); _waitingParameter = null; } /// <summary> /// Gets the count. /// </summary> /// <value>The count.</value> public int Count { get { return _parameters.Count; } } /// <summary> /// Adds the specified argument. /// </summary> /// <param name="argument">The argument.</param> /// <param name="value">The value.</param> public void Add(string argument, string value) { if (!_parameters.ContainsKey(argument)) _parameters.Add(argument, new Collection<string>()); _parameters[argument].Add(value); } public void AddSingle(string argument, string value) { if (!_parameters.ContainsKey(argument)) _parameters.Add(argument, new Collection<string>()); else throw new ArgumentException(string.Format("Argument {0} has already been defined", argument)); _parameters[argument].Add(value); } public void Remove(string argument) { if (_parameters.ContainsKey(argument)) _parameters.Remove(argument); } /// <summary> /// Determines whether the specified argument is true. /// </summary> /// <param name="argument">The argument.</param> /// <returns> /// <c>true</c> if the specified argument is true; otherwise, <c>false</c>. /// </returns> public bool IsTrue(string argument) { AssertSingle(argument); var arg = this[argument]; return arg != null && arg[0].Equals("true", StringComparison.OrdinalIgnoreCase); } private void AssertSingle(string argument) { if (this[argument] != null && this[argument].Count > 1) throw new ArgumentException(string.Format("{0} has been specified more than once, expecting single value", argument)); } public string Single(string argument) { AssertSingle(argument); //only return value if its NOT true, there is only a single item for that argument //and the argument is defined if (this[argument] != null && !IsTrue(argument)) return this[argument][0]; return null; } public bool Exists(string argument) { return (this[argument] != null && this[argument].Count > 0); } /// <summary> /// Gets the <see cref="System.Collections.ObjectModel.Collection<T>"/> with the specified parameter. /// </summary> /// <value></value> public Collection<string> this[string parameter] { get { return _parameters.ContainsKey(parameter) ? _parameters[parameter] : null; } } } }