166 lines
6.5 KiB
C#
166 lines
6.5 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.ComponentModel;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Reflection;
|
|
|
|
namespace KattekerCreator.Helper
|
|
{
|
|
public class SimpleCommandLineParser<TObject> where TObject : new()
|
|
{
|
|
private TObject _parsedObject;
|
|
|
|
public SimpleCommandLineParser(IEnumerable<string> args)
|
|
{
|
|
Parse(args);
|
|
}
|
|
|
|
private IDictionary<string, string[]> Arguments { get; } = new Dictionary<string, string[]>();
|
|
|
|
public bool Contains(string name) => Arguments.ContainsKey(name);
|
|
|
|
public TObject GetObject()
|
|
{
|
|
if (!EqualityComparer<TObject>.Default.Equals(_parsedObject, default(TObject)))
|
|
return _parsedObject;
|
|
_parsedObject = new TObject();
|
|
try
|
|
{
|
|
LoopProperties(pi =>
|
|
{
|
|
var displayName = GetDisplayName(pi);
|
|
if (displayName == null) return;
|
|
if (!Arguments.TryGetValue(displayName.ToLowerInvariant(), out var argument)) return;
|
|
if (pi.PropertyType == typeof(bool))
|
|
{
|
|
pi.SetValue(_parsedObject, true);
|
|
return;
|
|
}
|
|
if (pi.PropertyType.IsArray)
|
|
pi.SetValue(_parsedObject, argument);
|
|
else
|
|
pi.SetValue(_parsedObject, argument.FirstOrDefault());
|
|
});
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Log.WriteErrorLine("Error parsing commandline arguments: " + e.Message);
|
|
ShowHelp();
|
|
}
|
|
return _parsedObject;
|
|
}
|
|
|
|
public void ShowHelp(TextWriter textWriter = null)
|
|
{
|
|
if (textWriter == null) textWriter = Console.Out;
|
|
var executable = Assembly.GetExecutingAssembly().GetName().Name + ".exe";
|
|
var assemblyTitle = ((AssemblyTitleAttribute) Attribute.GetCustomAttribute(Assembly.GetExecutingAssembly(), typeof(AssemblyTitleAttribute), false))?.Title ?? executable;
|
|
var assemblyDescription = ((AssemblyDescriptionAttribute) Attribute.GetCustomAttribute(Assembly.GetExecutingAssembly(), typeof(AssemblyDescriptionAttribute), false))?.Description;
|
|
|
|
textWriter.WriteLine();
|
|
textWriter.WriteLine(assemblyTitle);
|
|
textWriter.WriteLine();
|
|
textWriter.WriteLine(assemblyDescription);
|
|
textWriter.WriteLine();
|
|
textWriter.WriteLine(executable + " <options>");
|
|
textWriter.WriteLine();
|
|
var dict = new Dictionary<string, string>();
|
|
LoopProperties(pi =>
|
|
{
|
|
var displayName = GetDisplayName(pi);
|
|
if (displayName == null) return;
|
|
var description = GetDescription(pi);
|
|
if (pi.PropertyType == typeof(bool)) description = "(Switch) " + description;
|
|
dict.Add(displayName, description);
|
|
});
|
|
var longestWord = dict.Keys.Max(x => x.Length);
|
|
foreach (var kv in dict)
|
|
{
|
|
textWriter.Write("-" + kv.Key.PadRight(longestWord + 3, ' '));
|
|
textWriter.WriteLine(kv.Value);
|
|
}
|
|
textWriter.WriteLine();
|
|
textWriter.WriteLine("A switch will be set to true, if it will called.");
|
|
textWriter.WriteLine($"Example: {executable} <Switch>");
|
|
textWriter.WriteLine();
|
|
textWriter.WriteLine("A parameter will be set.");
|
|
textWriter.WriteLine($"Example: {executable} <Key> \"Value\"");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Shows the current set options.
|
|
/// </summary>
|
|
/// <param name="textWriter">If not set Console.Out will be set.</param>
|
|
public void ShowProgramArguments(TextWriter textWriter = null)
|
|
{
|
|
if (textWriter == null) textWriter = Console.Out;
|
|
LoopProperties(pi =>
|
|
{
|
|
var displayName = GetDisplayName(pi) ?? pi.Name;
|
|
var value = pi.GetValue(_parsedObject);
|
|
textWriter.Write(displayName.PadRight(20, ' '));
|
|
if (value == null)
|
|
{
|
|
textWriter.WriteLine("<NOT SET>");
|
|
}
|
|
else
|
|
{
|
|
if (value.GetType().IsArray)
|
|
{
|
|
var arrayAsString = ((IEnumerable) value)
|
|
.Cast<object>()
|
|
.Aggregate(string.Empty, (current, x) => current + x?.ToString() + ", ");
|
|
textWriter.WriteLine(arrayAsString);
|
|
}
|
|
else
|
|
{
|
|
textWriter.WriteLine(value.ToString());
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
private static TAttribute GetAttribute<TAttribute>(MemberInfo memberInfo) where TAttribute : Attribute =>
|
|
(TAttribute) Attribute.GetCustomAttribute(memberInfo, typeof(TAttribute));
|
|
|
|
private static string GetDescription(MemberInfo memberInfo) => GetAttribute<DescriptionAttribute>(memberInfo)?.Description;
|
|
|
|
private static string GetDisplayName(MemberInfo memberInfo) => GetAttribute<DisplayNameAttribute>(memberInfo)?.DisplayName;
|
|
|
|
private static void LoopProperties(Action<PropertyInfo> action)
|
|
{
|
|
var properties = typeof(TObject).GetProperties(BindingFlags.Public | BindingFlags.Instance);
|
|
foreach (var propertyInfo in properties)
|
|
action.Invoke(propertyInfo);
|
|
}
|
|
|
|
private void Parse(IEnumerable<string> args)
|
|
{
|
|
var currentName = "";
|
|
var values = new List<string>();
|
|
foreach (var arg in args)
|
|
{
|
|
if (arg.StartsWith("-", StringComparison.Ordinal))
|
|
{
|
|
if (!string.IsNullOrWhiteSpace(currentName))
|
|
Arguments[currentName.ToLowerInvariant()] = values.ToArray();
|
|
values.Clear();
|
|
currentName = arg.Substring(1);
|
|
}
|
|
else if (string.IsNullOrWhiteSpace(currentName))
|
|
{
|
|
Arguments[arg] = new string[0];
|
|
}
|
|
else
|
|
{
|
|
values.Add(arg);
|
|
}
|
|
}
|
|
|
|
if (currentName != "")
|
|
Arguments[currentName.ToLowerInvariant()] = values.ToArray();
|
|
}
|
|
}
|
|
} |