130 lines
4.0 KiB
C#
130 lines
4.0 KiB
C#
using System.Collections;
|
|
using System.ComponentModel;
|
|
using System.Reflection;
|
|
|
|
namespace Nerfed.Builder;
|
|
|
|
|
|
public class ArgsParser<TArgs> where TArgs : new()
|
|
{
|
|
private enum ArgType
|
|
{
|
|
None,
|
|
Key,
|
|
Value
|
|
}
|
|
|
|
public TArgs Arguments { get; }
|
|
|
|
private readonly string[] args;
|
|
private readonly Dictionary<string, PropertyInfo> argKeyPropertyMap = new Dictionary<string, PropertyInfo>();
|
|
|
|
public ArgsParser(string[] args)
|
|
{
|
|
this.args = args;
|
|
Arguments = new TArgs();
|
|
PropertyInfo[] properties = Arguments.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public);
|
|
foreach (PropertyInfo property in properties)
|
|
{
|
|
ArgumentAttribute argAttribute = property.GetCustomAttribute<ArgumentAttribute>();
|
|
if (argAttribute == null || string.IsNullOrEmpty(argAttribute.ArgKey))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
argKeyPropertyMap.Add(argAttribute.ArgKey, property);
|
|
}
|
|
}
|
|
|
|
public bool Parse()
|
|
{
|
|
PropertyInfo property = null;
|
|
ArgType lastArgType = ArgType.None;
|
|
|
|
for (int i = 0; i < args.Length; i++)
|
|
{
|
|
string arg = args[i];
|
|
if (arg[0] == '-')
|
|
{
|
|
if (!argKeyPropertyMap.TryGetValue(arg, out property))
|
|
{
|
|
Console.Error.WriteLine($"Invalid argument: {arg}, no such argument key exists");
|
|
return false;
|
|
}
|
|
|
|
// Boolean arguments require no value, set to true immidiately.
|
|
if (property.PropertyType == typeof(bool))
|
|
{
|
|
property.SetValue(Arguments, true);
|
|
lastArgType = ArgType.Value;
|
|
}
|
|
else
|
|
{
|
|
lastArgType = ArgType.Key;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (lastArgType == ArgType.None)
|
|
{
|
|
Console.Error.WriteLine($"Invalid argument: {arg}, no argument key was provided");
|
|
return false;
|
|
}
|
|
|
|
Type propertyType = property.PropertyType;
|
|
if (propertyType.IsArray)
|
|
{
|
|
throw new InvalidOperationException("Arrays are not supported, use List<T> instead");
|
|
}
|
|
|
|
bool propertyTypeIsList = propertyType.IsGenericType && propertyType.GetGenericTypeDefinition() == typeof(List<>);
|
|
if (propertyTypeIsList)
|
|
{
|
|
propertyType = propertyType.GenericTypeArguments[0];
|
|
}
|
|
|
|
TypeConverter typeConverter = TypeDescriptor.GetConverter(propertyType);
|
|
object value = typeConverter.ConvertFromString(arg);
|
|
|
|
if (value is string stringValue)
|
|
{
|
|
if (!string.IsNullOrEmpty(stringValue))
|
|
{
|
|
if (stringValue[0] == '"')
|
|
{
|
|
stringValue = stringValue.Substring(1, stringValue.Length - 1);
|
|
}
|
|
|
|
if (stringValue[^1] == '"')
|
|
{
|
|
stringValue = stringValue.Substring(0, stringValue.Length - 1);
|
|
}
|
|
|
|
value = stringValue;
|
|
}
|
|
}
|
|
|
|
if (propertyTypeIsList)
|
|
{
|
|
IList list = (IList)property.GetValue(Arguments);
|
|
if (list == null)
|
|
{
|
|
list = (IList)Activator.CreateInstance(property.PropertyType);
|
|
property.SetValue(Arguments, list);
|
|
}
|
|
|
|
list.Add(value);
|
|
}
|
|
else
|
|
{
|
|
property.SetValue(Arguments, value);
|
|
}
|
|
|
|
lastArgType = ArgType.Value;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
}
|