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 where TObject : new() { private TObject _parsedObject; public SimpleCommandLineParser(IEnumerable args) { Parse(args); } private IDictionary Arguments { get; } = new Dictionary(); public bool Contains(string name) => Arguments.ContainsKey(name); public TObject GetObject() { if (!EqualityComparer.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 + " "); textWriter.WriteLine(); var dict = new Dictionary(); 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} "); textWriter.WriteLine(); textWriter.WriteLine("A parameter will be set."); textWriter.WriteLine($"Example: {executable} \"Value\""); } /// /// Shows the current set options. /// /// If not set Console.Out will be set. 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(""); } else { if (value.GetType().IsArray) { var arrayAsString = ((IEnumerable) value) .Cast() .Aggregate(string.Empty, (current, x) => current + x?.ToString() + ", "); textWriter.WriteLine(arrayAsString); } else { textWriter.WriteLine(value.ToString()); } } }); } private static TAttribute GetAttribute(MemberInfo memberInfo) where TAttribute : Attribute => (TAttribute) Attribute.GetCustomAttribute(memberInfo, typeof(TAttribute)); private static string GetDescription(MemberInfo memberInfo) => GetAttribute(memberInfo)?.Description; private static string GetDisplayName(MemberInfo memberInfo) => GetAttribute(memberInfo)?.DisplayName; private static void LoopProperties(Action action) { var properties = typeof(TObject).GetProperties(BindingFlags.Public | BindingFlags.Instance); foreach (var propertyInfo in properties) action.Invoke(propertyInfo); } private void Parse(IEnumerable args) { var currentName = ""; var values = new List(); 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(); } } }