diff --git a/Nuclex.Support (PC).csproj b/Nuclex.Support (PC).csproj
index 4568858..462e7c5 100644
--- a/Nuclex.Support (PC).csproj
+++ b/Nuclex.Support (PC).csproj
@@ -179,6 +179,15 @@
SimpleRectanglePacker.Test
SimpleRectanglePacker.cs
+
+ false
+ CommandLineParser
+
+
+ false
+ CommandLineParser.Test
+ CommandLineParser.cs
+
false
PathHelper
@@ -308,7 +317,6 @@
-
diff --git a/Source/Parsing/CommandLineParser.Test.cs b/Source/Parsing/CommandLineParser.Test.cs
new file mode 100644
index 0000000..c5cb11d
--- /dev/null
+++ b/Source/Parsing/CommandLineParser.Test.cs
@@ -0,0 +1,59 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+#if UNITTEST
+
+using NUnit.Framework;
+
+namespace Nuclex.Support.Parsing {
+
+ /// Ensures that the command line parser is working properly
+ [TestFixture]
+ public class CommandLineParserTest {
+
+ /// Validates that normal arguments can be parsed
+ [Test]
+ public void TestPlainArguments() {
+ Assert.AreEqual(
+ true.ToString(),
+ new CommandLineParser(new string[] { "-hello" })["hello"],
+ "Argument with minus sign is recognized"
+ );
+ Assert.AreEqual(
+ true.ToString(),
+ new CommandLineParser(new string[] { "--hello" })["hello"],
+ "Argument with double minus sign is recognized"
+ );
+ Assert.AreEqual(
+ true.ToString(),
+ new CommandLineParser(new string[] { "/hello" })["hello"],
+ "Argument with slash is recognized"
+ );
+ }
+
+ /// Validates that argument assignments are working
+ [Test]
+ public void TestAssignments() {
+ Assert.AreEqual(
+ "world",
+ new CommandLineParser(new string[] { "-hello:world" })["hello"],
+ "Argument can be assigned with a double colon"
+ );
+ Assert.AreEqual(
+ "world",
+ new CommandLineParser(new string[] { "-hello=world" })["hello"],
+ "Argument can be assigned with a equality sign"
+ );
+ Assert.AreEqual(
+ "world",
+ new CommandLineParser(new string[] { "-hello", "world" })["hello"],
+ "Argument can be assigned with a space"
+ );
+ }
+
+ }
+
+} // namespace Nuclex.Support.Parsing
+
+#endif // UNITTEST
\ No newline at end of file
diff --git a/Source/Parsing/CommandLineParser.cs b/Source/Parsing/CommandLineParser.cs
new file mode 100644
index 0000000..5d788cf
--- /dev/null
+++ b/Source/Parsing/CommandLineParser.cs
@@ -0,0 +1,157 @@
+#region CPL License
+/*
+Nuclex Framework
+Copyright (C) 2002-2007 Nuclex Development Labs
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the IBM Common Public License as
+published by the IBM Corporation; either version 1.0 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
+IBM Common Public License for more details.
+
+You should have received a copy of the IBM Common Public
+License along with this library
+*/
+#endregion
+
+using System.Collections.Specialized;
+using System.Text.RegularExpressions;
+
+namespace Nuclex.Support.Parsing {
+
+ /// Parses an application's command line
+ ///
+ ///
+ /// Based on an article Richard Lopes published on "The Code Project" at
+ /// http://www.codeproject.com/csharp/command_line.asp
+ ///
+ ///
+ /// Valid forms for command line arguments: {-|/|--}param[{ |=|:}[{"|'}]value[{"|'}]]
+ ///
+ ///
+ ///
+ /// -param1 value1
+ /// --param2
+ /// /param3:"Test-:-work"
+ /// /param4=happy
+ /// -param5 '--=nice=--'
+ ///
+ ///
+ ///
+ public class CommandLineParser {
+
+ ///
+ /// Initializes a new command line parser using the running program's command line
+ ///
+ public CommandLineParser() : this(System.Environment.CommandLine) { }
+
+ /// Initializes a new command line parser
+ /// All supplied command line arguments as a single string
+ public CommandLineParser(string arguments)
+ : this(arguments.Split(new char[] { ' ', '\t' })) { }
+
+ /// Initializes a new command line parser
+ /// Arguments that have been passed in the command line
+ public CommandLineParser(string[] arguments) {
+ this.arguments = new StringDictionary();
+
+ string activeParameter = null;
+
+ foreach(string argument in arguments) {
+
+ // Look for arguments ('-', '/', '--') with their assignments ('=', ':')
+ string[] parts = splitter.Split(argument, 3);
+ switch(parts.Length) {
+
+ // Value found without an argument being specified (eg. file name)
+ case 1: {
+
+ if(activeParameter != null) {
+ if(!this.arguments.ContainsKey(activeParameter)) {
+ parts[0] = remover.Replace(parts[0], "$1");
+ this.arguments.Add(activeParameter, parts[0]);
+ }
+ activeParameter = null;
+ }
+
+ // Error: No argument is waiting for a value. Skip this argument.
+ break;
+ }
+
+ // Found an argument with no value assignment
+ case 2: {
+
+ // In case the previous argument is still waiting for a value we need to finish
+ // it up before switching to the argument we just found.
+ if(activeParameter != null)
+ if(!this.arguments.ContainsKey(activeParameter))
+ this.arguments.Add(activeParameter, true.ToString());
+
+ // Remember argument to allow for a later value assignment
+ activeParameter = parts[1];
+
+ break;
+ }
+
+ // Found an argument with a proper assignment declaration
+ case 3: {
+
+ // In case the previous argument is still waiting for a value we need to finish
+ // it up before switching to the argument we just found.
+ if(activeParameter != null)
+ if(!this.arguments.ContainsKey(activeParameter))
+ this.arguments.Add(activeParameter, true.ToString());
+
+ activeParameter = parts[1];
+
+ // Remove any quotes that might be enclosing this argument (",')
+ if(!this.arguments.ContainsKey(activeParameter)) {
+ parts[2] = remover.Replace(parts[2], "$1");
+ this.arguments.Add(activeParameter, parts[2]);
+ }
+
+ activeParameter = null;
+
+ break;
+ }
+ }
+ }
+
+ // In case the previous argument is still waiting for a value we need to finish
+ // it up before leaving the parsing method.
+ if(activeParameter != null) {
+ if(!this.arguments.ContainsKey(activeParameter)) {
+ this.arguments.Add(activeParameter, true.ToString());
+ }
+ }
+ }
+
+ /// Returns the value of an argument by the argument's name
+ /// Name of the argument whose value will be returned
+ /// The value of the argument with the specified name
+ public string this[string argumentName] {
+ get { return this.arguments[argumentName]; }
+ }
+
+ ///
+ /// Regular Expression used to split the arguments and their assigned values
+ ///
+ private static Regex splitter =
+ new Regex(@"^-{1,2}|^/|=|:", RegexOptions.IgnoreCase | RegexOptions.Compiled);
+
+ ///
+ /// Regular Expression used to remove quotations around an argument's value
+ ///
+ private static Regex remover =
+ new Regex(@"^['""]?(.*?)['""]?$", RegexOptions.IgnoreCase | RegexOptions.Compiled);
+
+ /// Stores the parsed arguments
+ private StringDictionary arguments;
+
+ }
+
+} // namespace Nuclex.Support.Parsing