Create a arguments system

This commit is contained in:
zontreck 2024-12-16 15:31:10 -07:00
parent ad7b619706
commit b217d463eb
5 changed files with 477 additions and 0 deletions

View file

@ -0,0 +1,57 @@
using System.Collections.Generic;
using LibAC.NBT.API;
namespace LibAC.Arguments;
public static class ArgumentHelpers
{
/// <summary>
/// Generates a command-line help message for the provided arguments.
/// </summary>
/// <param name="arguments">The list of arguments to generate help for.</param>
/// <returns>A string containing the help message.</returns>
public static string GenerateHelpMessage(List<IArgument> arguments, string ProgramName)
{
StringBuilder helpMessage = new StringBuilder();
helpMessage.Append($"Usage: {ProgramName} [options]\n");
foreach (var arg in arguments)
{
string description = GetArgumentDescription(arg);
string valueType = arg.GetValueType().ToString();
helpMessage.Append($" --{arg.Key} [{valueType}] {description}\n");
}
return helpMessage.ToString();
}
/// <summary>
/// Gets a description for an argument. This can be extended to provide more info.
/// </summary>
/// <param name="argument">The argument for which to generate a description.</param>
/// <returns>A description of the argument.</returns>
private static string GetArgumentDescription(IArgument argument)
{
// You can extend this to add more detailed descriptions for specific arguments
return argument.HasValue() ? "Assigned value: " + argument.GetValue() : "No value assigned";
}
/// <summary>
/// Retrieves the type of an argument in a human-readable format.
/// </summary>
/// <param name="argument">The argument to get the type for.</param>
/// <returns>A string describing the argument type.</returns>
private static string GetArgumentType(IArgument argument)
{
return argument.GetValueType() switch
{
ArgumentType.String => "string",
ArgumentType.Integer => "integer",
ArgumentType.Boolean => "boolean",
ArgumentType.Float => "float",
ArgumentType.Double => "double",
_ => "unknown"
};
}
}

View file

@ -0,0 +1,75 @@
using System;
using System.Collections.Generic;
namespace LibAC.Arguments;
public class ArgumentParser
{
public List<IArgument> Arguments { get; private set; }
public ArgumentParser()
{
Arguments = new List<IArgument>();
}
/// <summary>
/// Parses a string array of arguments.
/// </summary>
/// <param name="args">The string array of arguments to parse.</param>
public void Parse(string[] args)
{
for (int i = 0; i < args.Length; i++)
{
var arg = args[i];
if (arg.StartsWith("--"))
{
string key = arg.Substring(2); // Remove the '--' part of the argument
object? value = null;
// Check if the argument has a value attached (either --arg=value or --arg value)
if (i + 1 < args.Length && !args[i + 1].StartsWith("--"))
{
value = args[i + 1]; // --arg value
i++; // Skip the next argument as it is the value
}
else if (arg.Contains("="))
{
value = arg.Substring(arg.IndexOf('=') + 1); // --arg=value
}
// Determine the argument type and add it to the list
if (int.TryParse(value?.ToString(), out var intValue))
{
Arguments.Add(new IntegerArgument(key, intValue));
}
else if (bool.TryParse(value?.ToString(), out var boolValue))
{
Arguments.Add(new BooleanArgument(key, boolValue));
}
else if (float.TryParse(value?.ToString(), out var floatValue))
{
Arguments.Add(new FloatArgument(key, floatValue));
}
else if (double.TryParse(value?.ToString(), out var doubleValue))
{
Arguments.Add(new DoubleArgument(key, doubleValue));
}
else
{
// Default to StringArgument if no matching type is found
Arguments.Add(new StringArgument(key, value?.ToString()));
}
}
}
}
/// <summary>
/// Retrieves an argument by its key.
/// </summary>
/// <param name="key">The key of the argument to retrieve.</param>
/// <returns>The IArgument associated with the key, or null if not found.</returns>
public IArgument? GetArgument(string key)
{
return Arguments.Find(arg => arg.Key.Equals(key, StringComparison.OrdinalIgnoreCase));
}
}

184
Arguments/Arguments.cs Normal file
View file

@ -0,0 +1,184 @@
using System;
using System.Collections.Generic;
namespace LibAC.Arguments
{
/// <summary>
/// Represents a collection of arguments.
/// </summary>
public class Arguments
{
/// <summary>
/// The dictionary containing argument names and their corresponding <see cref="IArgument"/> instances.
/// </summary>
private readonly Dictionary<string, IArgument> _arguments;
/// <summary>
/// Initializes a new instance of the <see cref="Arguments"/> class.
/// </summary>
public Arguments()
{
_arguments = new Dictionary<string, IArgument>(StringComparer.OrdinalIgnoreCase);
}
/// <summary>
/// Adds an argument to the collection.
/// </summary>
/// <param name="argument">The argument to add.</param>
/// <exception cref="ArgumentException">Thrown if an argument with the same key already exists.</exception>
public void AddArgument(IArgument argument)
{
if (_arguments.ContainsKey(argument.Key))
throw new ArgumentException($"An argument with the key '{argument.Key}' already exists.");
_arguments[argument.Key] = argument;
}
/// <summary>
/// Retrieves an argument by its key.
/// </summary>
/// <param name="key">The key of the argument to retrieve.</param>
/// <returns>The <see cref="IArgument"/> associated with the key.</returns>
/// <exception cref="KeyNotFoundException">Thrown if the key is not found in the collection.</exception>
public IArgument GetArgument(string key)
{
if (!_arguments.TryGetValue(key, out var argument))
throw new KeyNotFoundException($"No argument found with the key '{key}'.");
return argument;
}
/// <summary>
/// Checks if an argument with the specified key exists in the collection.
/// </summary>
/// <param name="key">The key to check for.</param>
/// <returns><c>true</c> if an argument with the key exists; otherwise, <c>false</c>.</returns>
public bool HasArg(string key)
{
return _arguments.ContainsKey(key); // Dictionary method remains unchanged
}
/// <summary>
/// Removes an argument from the collection by its key.
/// </summary>
/// <param name="key">The key of the argument to remove.</param>
/// <returns><c>true</c> if the argument was removed; otherwise, <c>false</c>.</returns>
public bool RemoveArgument(string key)
{
return _arguments.Remove(key);
}
/// <summary>
/// Gets all arguments in the collection.
/// </summary>
/// <returns>An enumerable of all <see cref="IArgument"/> instances in the collection.</returns>
public IEnumerable<IArgument> GetAllArguments()
{
return _arguments.Values;
}
/// <summary>
/// Clears all arguments from the collection.
/// </summary>
public void Clear()
{
_arguments.Clear();
}
}
public class ArgumentBuilder
{
private readonly Arguments _arguments;
public ArgumentBuilder()
{
_arguments = new Arguments();
}
/// <summary>
/// Adds a predefined argument for a string type.
/// </summary>
public ArgumentBuilder AddStringArgument(string key, string? value = null, bool required = false)
{
IArgument arg = new StringArgument(key, value);
arg.required = required;
_arguments.AddArgument(arg);
return this;
}
/// <summary>
/// Adds a predefined argument for an integer type.
/// </summary>
public ArgumentBuilder AddIntegerArgument(string key, int? value = null, bool required = false)
{
IArgument arg = new IntegerArgument(key, value);
arg.required = required;
_arguments.AddArgument(arg);
return this;
}
/// <summary>
/// Adds a predefined argument for a boolean type.
/// </summary>
public ArgumentBuilder AddBooleanArgument(string key, bool? value = null, bool required = false)
{
IArgument arg = new BooleanArgument(key, value);
arg.required = required;
_arguments.AddArgument(arg);
return this;
}
/// <summary>
/// Adds a predefined argument for a float type.
/// </summary>
public ArgumentBuilder AddFloatArgument(string key, float? value = null, bool required = false)
{
IArgument arg = new FloatArgument(key, value);
arg.required = required;
_arguments.AddArgument(arg);
return this;
}
/// <summary>
/// Adds a predefined argument for a double type.
/// </summary>
public ArgumentBuilder AddDoubleArgument(string key, double? value = null, bool required = false)
{
IArgument arg = new DoubleArgument(key, value);
arg.required = required;
_arguments.AddArgument(arg);
return this;
}
/// <summary>
/// Adds a predefined 'help' argument (usually a flag).
/// </summary>
public ArgumentBuilder AddHelpArgument()
{
_arguments.AddArgument(new BooleanArgument("help", false)); // or true based on logic
return this;
}
/// <summary>
/// Adds a predefined 'version' argument.
/// </summary>
public ArgumentBuilder AddVersionArgument()
{
_arguments.AddArgument(new BooleanArgument("version"));
return this;
}
/// <summary>
/// Returns the constructed Arguments object containing all the added arguments.
/// </summary>
public Arguments Build()
{
return _arguments;
}
}
}

49
Arguments/IArgument.cs Normal file
View file

@ -0,0 +1,49 @@
namespace LibAC.Arguments
{
/// <summary>
/// Defines the base interface for an argument.
/// </summary>
public interface IArgument
{
/// <summary>
/// Gets the unique key identifying the argument.
/// The setter is private to ensure immutability outside the implementing class.
/// </summary>
string Key { get; set; }
/// <summary>
/// Obtains the value of the argument.
/// </summary>
/// <returns>The value of the argument as an object, or null if no value is present.</returns>
object? GetValue();
/// <summary>
/// Gets the type of the value this argument holds.
/// </summary>
/// <returns>The <see cref="ArgumentType"/> of the argument value.</returns>
ArgumentType GetValueType();
/// <summary>
/// Indicates whether this argument has a value assigned.
/// </summary>
/// <returns><c>true</c> if the argument has a value; otherwise, <c>false</c>.</returns>
bool HasValue();
/// <summary>
/// For CLI Help only. Indicates whether the argument is required or not
/// </summary>
bool required { set; }
}
/// <summary>
/// Defines the types of arguments supported.
/// </summary>
public enum ArgumentType
{
String,
Integer,
Boolean,
Float,
Double
}
}

112
Arguments/Types.cs Normal file
View file

@ -0,0 +1,112 @@
namespace LibAC.Arguments
{
/// <summary>
/// Argument class for String values.
/// </summary>
public class StringArgument : IArgument
{
public string Key { get; set; }
private string? value;
public StringArgument(string key, string? value = null)
{
Key = key;
this.value = value;
}
public object? GetValue() => value;
public ArgumentType GetValueType() => ArgumentType.String;
public bool HasValue() => value != null;
public bool required { get; set; }
}
/// <summary>
/// Argument class for Integer values.
/// </summary>
public class IntegerArgument : IArgument
{
public string Key { get; set; }
private int? value;
public IntegerArgument(string key, int? value = null)
{
Key = key;
this.value = value;
}
public object? GetValue() => value;
public ArgumentType GetValueType() => ArgumentType.Integer;
public bool HasValue() => value.HasValue;
public bool required { get; set; }
}
/// <summary>
/// Argument class for Boolean values.
/// </summary>
public class BooleanArgument : IArgument
{
public string Key { get; set; }
private bool? value;
public BooleanArgument(string key, bool? value = null)
{
Key = key;
this.value = value;
}
public object? GetValue() => value;
public ArgumentType GetValueType() => ArgumentType.Boolean;
public bool HasValue() => value.HasValue;
public bool required { get; set; }
}
/// <summary>
/// Argument class for Float values.
/// </summary>
public class FloatArgument : IArgument
{
public string Key { get; set; }
private float? value;
public FloatArgument(string key, float? value = null)
{
Key = key;
this.value = value;
}
public object? GetValue() => value;
public ArgumentType GetValueType() => ArgumentType.Float;
public bool HasValue() => value.HasValue;
public bool required { get; set; }
}
/// <summary>
/// Argument class for Double values.
/// </summary>
public class DoubleArgument : IArgument
{
public string Key { get; set; }
private double? value;
public DoubleArgument(string key, double? value = null)
{
Key = key;
this.value = value;
}
public object? GetValue() => value;
public ArgumentType GetValueType() => ArgumentType.Double;
public bool HasValue() => value.HasValue;
public bool required { get; set; }
}
}