// There is no license for this code. You are free to modify and redistribute it. Also, you can delete this comment.
// Original source code: https://github.com/wertrain/command-line-parser-cs (Version 0.1)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
namespace CommandLineParser
{
///
/// Option attribute
///
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
public sealed class Option : Attribute
{
///
/// Constructor
///
public Option()
{
}
///
/// Constructor
///
///
public Option(string longName)
{
LongName = longName;
}
///
/// Constructor
///
///
public Option(char shortName)
{
ShortName = shortName;
}
///
/// Constructor
///
///
///
public Option(char shortName, string longName)
{
ShortName = shortName;
LongName = longName;
}
///
/// long name command option
///
public string LongName { get; private set; }
///
/// short name command option
///
public char ShortName { get; private set; }
///
/// command option
///
public string HelpText { get; set; }
///
/// command option
///
public bool Required { get; set; }
}
///
/// Results type of parse
///
public enum ParserResultType
{
///
///
///
Parsed = 0,
///
///
///
NotParsed
}
///
/// Results of parse
///
///
public class ParserResult
{
///
///
///
///
internal ParserResult(ParserResultType tag, T value)
{
Tag = tag;
Value = value;
}
///
///
///
public ParserResultType Tag { get; }
///
///
///
public T Value { get; }
}
///
/// Utility for parser
///
static class ParserUtility
{
///
///
///
///
///
///
public static T ConvertValue(this string input)
{
var converter = System.ComponentModel.TypeDescriptor.GetConverter(typeof(T));
if (converter != null)
{
return (T)converter.ConvertFromString(input);
}
return default(T);
}
///
///
///
///
///
///
///
///
public static bool SetValueToProperty(PropertyInfo property, T value, string param)
{
switch (property.PropertyType.Name)
{
case "Boolean":
if (string.IsNullOrEmpty(param))
{
property.SetValue(value, true);
}
else
{
switch (param.ToLower())
{
case "true": property.SetValue(value, true); return true;
case "false": property.SetValue(value, false); return true;
}
}
return false;
case "Byte": property.SetValue(value, ConvertValue(param)); break;
case "SByte": property.SetValue(value, ConvertValue(param)); break;
case "Char": property.SetValue(value, ConvertValue(param)); break;
case "Decimal": property.SetValue(value, ConvertValue(param)); break;
case "Double": property.SetValue(value, ConvertValue(param)); break;
case "Single": property.SetValue(value, ConvertValue(param)); break;
case "Int32": property.SetValue(value, ConvertValue(param)); break;
case "UInt32": property.SetValue(value, ConvertValue(param)); break;
case "Int64": property.SetValue(value, ConvertValue(param)); break;
case "UInt64": property.SetValue(value, ConvertValue(param)); break;
case "Int16": property.SetValue(value, ConvertValue(param)); break;
case "UInt16": property.SetValue(value, ConvertValue(param)); break;
case "String":
property.SetValue(value, param);
return !string.IsNullOrEmpty(param);
}
return true;
}
}
///
/// Arguments parser
///
public class Parser
{
///
/// Help command
///
private const string HelpLongName = "help";
///
/// Parse command line
///
///
///
///
public static ParserResult Parse(string args) where T : new()
{
var enumerable = args.Split();
return Parse(enumerable);
}
///
/// Parse command line
///
///
///
///
public static ParserResult Parse(IEnumerable args) where T : new()
{
if (args.Count() == 0)
{
ShowHelp();
return new ParserResult(ParserResultType.NotParsed, new T());
}
var longNameDictionary = new Dictionary>();
var shortNameDictionary = new Dictionary>();
foreach (var property in typeof(T).GetProperties())
{
var attributes = Attribute.GetCustomAttributes(property, typeof(Option));
foreach (Option option in attributes)
{
if (!string.IsNullOrWhiteSpace(option.LongName))
{
longNameDictionary.Add(option.LongName, new Tuple(property.Name, option));
}
if (option.ShortName != '\0')
{
shortNameDictionary.Add(option.ShortName, new Tuple(property.Name, option));
}
}
}
var value = new T();
var resultTag = ParserResultType.Parsed;
for (int i = 0, max = args.Count(); i < max; ++i)
{
var arg = args.ElementAt(i);
Tuple pair = null;
if (arg.StartsWith("--"))
{
string command = arg.Substring(2);
if (command == HelpLongName)
{
ShowHelp();
return new ParserResult(ParserResultType.Parsed, new T());
}
if (longNameDictionary.ContainsKey(command))
{
pair = longNameDictionary[command];
}
}
else if (arg.StartsWith("-"))
{
string command = arg.Substring(1);
if (command.Length != 1)
{
continue;
}
if (shortNameDictionary.ContainsKey(command[0]))
{
pair = shortNameDictionary[command[0]];
}
}
if (pair == null)
{
continue;
}
foreach (var property in typeof(T).GetProperties())
{
if (pair.Item1 == property.Name)
{
string param = string.Empty;
if (args.Count() > i + 1)
{
param = args.ElementAt(i + 1);
}
try
{
if (ParserUtility.SetValueToProperty(property, value, param))
{
++i;
}
}
catch
{
resultTag = ParserResultType.NotParsed;
}
}
}
}
return new ParserResult(resultTag, value);
}
///
/// Show help
///
public static void ShowHelp()
{
int SpacePaddingSize = 12;
var asm = Assembly.GetExecutingAssembly();
Console.WriteLine("{0} {1}", System.IO.Path.GetFileNameWithoutExtension(asm.Location), asm.GetName().Version);
foreach (var property in typeof(T).GetProperties())
{
var attributes = Attribute.GetCustomAttributes(property, typeof(Option));
foreach (Option attribute in attributes)
{
Console.Write("-{0}, --{1,-" + SpacePaddingSize + "} ", attribute.ShortName, attribute.LongName);
if (attribute.Required)
{
Console.Write("[Required]");
}
Console.WriteLine("{0}", attribute.HelpText);
}
}
Console.WriteLine("--{0,-" + (SpacePaddingSize + HelpLongName.Length) + "} {1}", HelpLongName, "Display this help screen.");
}
}
}