Initial commit with code already here.
This commit is contained in:
commit
9fdd499d7a
6
.gitignore
vendored
Normal file
6
.gitignore
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
# Visual Studio things.
|
||||
.vs/
|
||||
|
||||
# Build Stuff
|
||||
*/bin
|
||||
*/obj
|
||||
25
ArgumentBase.sln
Normal file
25
ArgumentBase.sln
Normal file
@ -0,0 +1,25 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.8.34309.116
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ArgumentBase", "ArgumentBase\ArgumentBase.csproj", "{E6AFC35D-D69A-4956-9ED4-AF0276192EE8}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{E6AFC35D-D69A-4956-9ED4-AF0276192EE8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{E6AFC35D-D69A-4956-9ED4-AF0276192EE8}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{E6AFC35D-D69A-4956-9ED4-AF0276192EE8}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{E6AFC35D-D69A-4956-9ED4-AF0276192EE8}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {DF77961F-683C-444B-9866-FB4C081B3E24}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
12
ArgumentBase/ArgFlagInfo.cs
Normal file
12
ArgumentBase/ArgFlagInfo.cs
Normal file
@ -0,0 +1,12 @@
|
||||
using System.Reflection;
|
||||
|
||||
namespace ArgumentBase;
|
||||
|
||||
public class ArgFlagInfo
|
||||
{
|
||||
public required string Name { get; init; }
|
||||
public required string Description { get; init; }
|
||||
public required PropertyInfo Property { get; init; }
|
||||
|
||||
internal ArgFlagInfo() { }
|
||||
}
|
||||
13
ArgumentBase/ArgParameterInfo.cs
Normal file
13
ArgumentBase/ArgParameterInfo.cs
Normal file
@ -0,0 +1,13 @@
|
||||
using System.Reflection;
|
||||
|
||||
namespace ArgumentBase;
|
||||
|
||||
public class ArgParameterInfo
|
||||
{
|
||||
public required int Order { get; init; }
|
||||
public required string Name { get; init; }
|
||||
public required string Description { get; init; }
|
||||
public required PropertyInfo Property { get; init; }
|
||||
|
||||
internal ArgParameterInfo() { }
|
||||
}
|
||||
12
ArgumentBase/ArgVariableInfo.cs
Normal file
12
ArgumentBase/ArgVariableInfo.cs
Normal file
@ -0,0 +1,12 @@
|
||||
using System.Reflection;
|
||||
|
||||
namespace ArgumentBase;
|
||||
|
||||
public class ArgVariableInfo
|
||||
{
|
||||
public required string Name { get; init; }
|
||||
public required string Description { get; init; }
|
||||
public required PropertyInfo Property { get; init; }
|
||||
|
||||
internal ArgVariableInfo() { }
|
||||
}
|
||||
291
ArgumentBase/ArgumentBase.cs
Normal file
291
ArgumentBase/ArgumentBase.cs
Normal file
@ -0,0 +1,291 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
|
||||
namespace ArgumentBase;
|
||||
|
||||
#pragma warning disable IL2070, IL2090 // Shut up.
|
||||
|
||||
public abstract class ArgumentBase<TSelf> where TSelf : ArgumentBase<TSelf>, new()
|
||||
{
|
||||
public static ReadOnlyCollection<ArgParameterInfo> Parameters { get; private set; }
|
||||
public static ReadOnlyCollection<ArgVariableInfo> Variables { get; private set; }
|
||||
public static ReadOnlyCollection<ArgFlagInfo> Flags { get; private set; }
|
||||
|
||||
public static ReadOnlyDictionary<string, string> ParameterDescriptions { get; private set; }
|
||||
public static ReadOnlyDictionary<string, string> VariableDescriptions { get; private set; }
|
||||
public static ReadOnlyDictionary<string, string> FlagDescriptions { get; private set; }
|
||||
public static ReadOnlyDictionary<string, PropertyInfo> VariableTable { get; private set; }
|
||||
public static ReadOnlyDictionary<string, PropertyInfo> FlagTable { get; private set; }
|
||||
|
||||
static ArgumentBase()
|
||||
{
|
||||
IEnumerable<PropertyInfo> allProps = typeof(TSelf).GetProperties().Where(x => x.SetMethod is not null);
|
||||
|
||||
List<ArgParameterInfo> parameters = [];
|
||||
List<ArgVariableInfo> variables = [];
|
||||
List<ArgFlagInfo> flags = [];
|
||||
|
||||
Dictionary<string, string> paramDesc = [], varDesc = [], flagDesc = [];
|
||||
Dictionary<string, PropertyInfo> varTable = [], flagTable = [];
|
||||
foreach (PropertyInfo prop in allProps)
|
||||
{
|
||||
IsParameterAttribute? paramAtt = prop.GetCustomAttribute<IsParameterAttribute>();
|
||||
IsVariableAttribute? varAtt = prop.GetCustomAttribute<IsVariableAttribute>();
|
||||
IsFlagAttribute? flagAtt = prop.GetCustomAttribute<IsFlagAttribute>();
|
||||
|
||||
if (paramAtt is not null)
|
||||
{
|
||||
ArgParameterInfo info = new()
|
||||
{
|
||||
Order = paramAtt.order,
|
||||
Name = paramAtt.name ?? prop.Name,
|
||||
Description = paramAtt.description,
|
||||
Property = prop
|
||||
};
|
||||
parameters.Add(info);
|
||||
|
||||
string trueName = info.Name.Trim();
|
||||
paramDesc.Add(trueName, info.Description);
|
||||
}
|
||||
if (varAtt is not null)
|
||||
{
|
||||
ArgVariableInfo info = new()
|
||||
{
|
||||
Name = varAtt.name ?? prop.Name,
|
||||
Description = varAtt.description,
|
||||
Property = prop
|
||||
};
|
||||
variables.Add(info);
|
||||
|
||||
string trueName = $"-{info.Name.Trim()}";
|
||||
varDesc.Add(trueName, info.Description);
|
||||
varTable.Add(trueName, info.Property);
|
||||
}
|
||||
if (flagAtt is not null)
|
||||
{
|
||||
ArgFlagInfo info = new()
|
||||
{
|
||||
Name = flagAtt.name ?? prop.Name,
|
||||
Description = flagAtt.description,
|
||||
Property = prop
|
||||
};
|
||||
flags.Add(info);
|
||||
|
||||
string trueName = $"--{info.Name.Trim()}";
|
||||
flagDesc.Add(trueName, info.Description);
|
||||
flagTable.Add(trueName, info.Property);
|
||||
}
|
||||
}
|
||||
|
||||
parameters.Sort((a, b) => a.Order.CompareTo(b.Order));
|
||||
Parameters = parameters.AsReadOnly();
|
||||
Variables = variables.AsReadOnly();
|
||||
Flags = flags.AsReadOnly();
|
||||
|
||||
// I would sort these, but I would need yet another for loop to do that.
|
||||
ParameterDescriptions = paramDesc.AsReadOnly();
|
||||
VariableDescriptions = varDesc.AsReadOnly();
|
||||
FlagDescriptions = flagDesc.AsReadOnly();
|
||||
VariableTable = varTable.AsReadOnly();
|
||||
FlagTable = flagTable.AsReadOnly();
|
||||
}
|
||||
|
||||
public static TSelf Parse(string[] args)
|
||||
{
|
||||
TSelf result = new();
|
||||
if (args.Length == 0) return result;
|
||||
|
||||
result.anyArguments = true;
|
||||
int parameterIndex = 0;
|
||||
List<string> unknownParams = [], unknownVars = [], unknownFlags = [];
|
||||
List<string> badValParams = [], badValVars = [];
|
||||
foreach (string arg in args)
|
||||
{
|
||||
if (arg.StartsWith("--")) // Flag
|
||||
{
|
||||
string name = arg[2..];
|
||||
ArgFlagInfo? flag = Flags.SingleOrDefault(x => x.Name.Equals(name, StringComparison.OrdinalIgnoreCase));
|
||||
|
||||
if (flag is null)
|
||||
{
|
||||
// Unknown flag.
|
||||
unknownFlags.Add(name);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Flip flag.
|
||||
bool original = (bool)flag.Property.GetValue(result)!;
|
||||
flag.Property.SetValue(result, !original);
|
||||
result.anyFlags = true;
|
||||
}
|
||||
else if (arg.StartsWith('-')) // Variable
|
||||
{
|
||||
int splitter = arg.IndexOf(':');
|
||||
string name = arg[1..splitter], valueStr = arg[(splitter + 1)..];
|
||||
ArgVariableInfo? var = Variables.SingleOrDefault(x => x.Name.Equals(name, StringComparison.OrdinalIgnoreCase));
|
||||
|
||||
if (var is null)
|
||||
{
|
||||
// Unknown variable.
|
||||
unknownVars.Add(name);
|
||||
continue;
|
||||
}
|
||||
|
||||
object? value = parseObject(valueStr, var.Property.PropertyType);
|
||||
if (value is null)
|
||||
{
|
||||
// Issue parsing the object.
|
||||
badValVars.Add(name);
|
||||
continue;
|
||||
}
|
||||
var.Property.SetValue(result, value);
|
||||
result.anyVars = true;
|
||||
}
|
||||
else // Parameter
|
||||
{
|
||||
if (parameterIndex >= Parameters.Count)
|
||||
{
|
||||
// Too many parameters.
|
||||
unknownParams.Add(arg);
|
||||
continue;
|
||||
}
|
||||
ArgParameterInfo param = Parameters[parameterIndex];
|
||||
parameterIndex++;
|
||||
|
||||
object? value = parseObject(arg, param.Property.PropertyType);
|
||||
if (value is null)
|
||||
{
|
||||
// Issue parsing the object.
|
||||
badValParams.Add(arg);
|
||||
continue;
|
||||
}
|
||||
param.Property.SetValue(result, value);
|
||||
result.anyParams = true;
|
||||
}
|
||||
}
|
||||
|
||||
int unknownArgs = unknownParams.Count + unknownVars.Count + unknownFlags.Count;
|
||||
if (unknownArgs > 0)
|
||||
{
|
||||
// Unknown arguments.
|
||||
StringBuilder warnMsg = new();
|
||||
warnMsg.Append($" \x1b[3;33m{unknownArgs} {(unknownArgs == 1 ? "argument was" : "arguments were")} not recognized:\n ");
|
||||
int lineLen = 2, maxLineLen = (int)(0.65 * Console.WindowWidth - 1);
|
||||
|
||||
foreach (string badParam in unknownParams)
|
||||
{
|
||||
if (lineLen + badParam.Length + 3 > maxLineLen)
|
||||
{
|
||||
warnMsg.Append("\n ");
|
||||
lineLen = 2;
|
||||
}
|
||||
warnMsg.Append($"\"\x1b[37m{badParam}\x1b[33m\" ");
|
||||
lineLen += badParam.Length + 3;
|
||||
}
|
||||
foreach (string badVar in unknownVars)
|
||||
{
|
||||
if (lineLen + badVar.Length + 4 > maxLineLen)
|
||||
{
|
||||
warnMsg.Append("\n ");
|
||||
lineLen = 2;
|
||||
}
|
||||
warnMsg.Append($"\"\x1b[36m-{badVar}\x1b[33m\" ");
|
||||
lineLen += badVar.Length + 4;
|
||||
}
|
||||
foreach (string badFlag in unknownFlags)
|
||||
{
|
||||
if (lineLen + badFlag.Length + 5 > maxLineLen)
|
||||
{
|
||||
warnMsg.Append("\n ");
|
||||
lineLen = 2;
|
||||
}
|
||||
warnMsg.Append($"\"\x1b[90m--{badFlag}\x1b[33m\" ");
|
||||
lineLen += badFlag.Length + 5;
|
||||
}
|
||||
warnMsg.AppendLine("\x1b[0m");
|
||||
Console.WriteLine(warnMsg);
|
||||
}
|
||||
int badValArgs = badValParams.Count + badValVars.Count;
|
||||
if (badValArgs > 0)
|
||||
{
|
||||
// Issue parsing arguments.
|
||||
StringBuilder warnMsg = new();
|
||||
warnMsg.Append($" \x1b[3;33m{badValArgs} {(badValArgs == 1 ? "value" : "values")} couldn't be parsed:\n ");
|
||||
int lineLen = 2, maxLineLen = (int)(0.65 * Console.WindowWidth - 1);
|
||||
|
||||
foreach (string badParam in badValParams)
|
||||
{
|
||||
if (lineLen + badParam.Length + 3 > maxLineLen)
|
||||
{
|
||||
warnMsg.Append("\n ");
|
||||
lineLen = 2;
|
||||
}
|
||||
warnMsg.Append($"\"\x1b[37m{badParam}\x1b[33m\" ");
|
||||
lineLen += badParam.Length + 3;
|
||||
}
|
||||
foreach (string badVar in badValVars)
|
||||
{
|
||||
if (lineLen + badVar.Length + 4 > maxLineLen)
|
||||
{
|
||||
warnMsg.Append("\n ");
|
||||
lineLen = 2;
|
||||
}
|
||||
warnMsg.Append($"\"\x1b[36m-{badVar}\x1b[33m\" ");
|
||||
lineLen += badVar.Length + 4;
|
||||
}
|
||||
warnMsg.AppendLine("\x1b[0m");
|
||||
Console.WriteLine(warnMsg);
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
static object? parseObject(string value, Type desired)
|
||||
{
|
||||
if (desired == typeof(string)) return value;
|
||||
else if (desired.IsEnum) return Enum.TryParse(desired, value, true, out object? enumResult) ? enumResult : null;
|
||||
else if (desired.GetInterface("IParsable`1") is null) throw new("Type must derive from IParsable. Sorry.");
|
||||
else
|
||||
{
|
||||
// A bit large. Couldn't condense into a single lambda because I wanted to cache the parameters.
|
||||
// I have to do all this weird stuff as a whole to be able to parse any object that derives
|
||||
// from IParsable, making extra stuff easier to implement.
|
||||
MethodInfo tryParseMethod = (from x in desired.GetMethods()
|
||||
let parameters = x.GetParameters()
|
||||
let goodName = x.Name == "TryParse"
|
||||
let goodAttributes = x.IsPublic && x.IsStatic
|
||||
let goodParams = parameters.Length == 2
|
||||
&& parameters[0].ParameterType == typeof(string)
|
||||
&& parameters[1].ParameterType.GetElementType() == desired
|
||||
where goodName && goodAttributes && goodParams
|
||||
select x).Single(); // Must exist according to IParsable.
|
||||
|
||||
// Output parameters are placed in the array.
|
||||
object?[] methodParams = [value, null];
|
||||
bool success = (bool)tryParseMethod.Invoke(null, methodParams)!;
|
||||
return success ? methodParams[1] : null;
|
||||
}
|
||||
}
|
||||
}
|
||||
public static void PrintParameters(string? keyFormat = null)
|
||||
{
|
||||
if (Parameters.Count == 0) return;
|
||||
else PrintHelper.PrintKeyValues("Parameters", 2, ParameterDescriptions.ToDictionary(), keyFormat: keyFormat ?? "\x1b[37m");
|
||||
}
|
||||
public static void PrintVariables()
|
||||
{
|
||||
if (Variables.Count == 0) return;
|
||||
else PrintHelper.PrintKeyValues("Variables", 2, VariableDescriptions.ToDictionary(), keyFormat: "\x1b[36m");
|
||||
}
|
||||
public static void PrintFlags()
|
||||
{
|
||||
if (Flags.Count == 0) return;
|
||||
else PrintHelper.PrintKeyValues("Flags", 2, FlagDescriptions.ToDictionary());
|
||||
}
|
||||
|
||||
public bool anyArguments;
|
||||
public bool anyParams, anyVars, anyFlags;
|
||||
}
|
||||
32
ArgumentBase/ArgumentBase.csproj
Normal file
32
ArgumentBase/ArgumentBase.csproj
Normal file
@ -0,0 +1,32 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>disable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
|
||||
<PackageId>ArgumentBase</PackageId>
|
||||
<Title>ArgumentBase</Title>
|
||||
<Version>1.0.0</Version>
|
||||
<Authors>That_One_Nerd</Authors>
|
||||
<Description>A small library that handles parsing console arguments.</Description>
|
||||
<Copyright>MIT</Copyright>
|
||||
<PackageReadmeFile>README.md</PackageReadmeFile>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||
<IsAotCompatible>True</IsAotCompatible>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
||||
<IsAotCompatible>True</IsAotCompatible>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Include="..\README.md">
|
||||
<Pack>True</Pack>
|
||||
<PackagePath>\</PackagePath>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
21
ArgumentBase/IsFlagAttribute.cs
Normal file
21
ArgumentBase/IsFlagAttribute.cs
Normal file
@ -0,0 +1,21 @@
|
||||
using System;
|
||||
|
||||
namespace ArgumentBase;
|
||||
|
||||
[AttributeUsage(AttributeTargets.Property)]
|
||||
public class IsFlagAttribute : Attribute
|
||||
{
|
||||
public readonly string description;
|
||||
public readonly string? name;
|
||||
|
||||
public IsFlagAttribute(string description)
|
||||
{
|
||||
this.description = description;
|
||||
name = null;
|
||||
}
|
||||
public IsFlagAttribute(string name, string description)
|
||||
{
|
||||
this.description = description;
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
24
ArgumentBase/IsParameterAttribute.cs
Normal file
24
ArgumentBase/IsParameterAttribute.cs
Normal file
@ -0,0 +1,24 @@
|
||||
using System;
|
||||
|
||||
namespace ArgumentBase;
|
||||
|
||||
[AttributeUsage(AttributeTargets.Property)]
|
||||
public class IsParameterAttribute : Attribute
|
||||
{
|
||||
public readonly int order;
|
||||
public readonly string description;
|
||||
public readonly string? name;
|
||||
|
||||
public IsParameterAttribute(int order, string description)
|
||||
{
|
||||
this.order = order;
|
||||
this.description = description;
|
||||
name = null;
|
||||
}
|
||||
public IsParameterAttribute(int order, string name, string description)
|
||||
{
|
||||
this.order = order;
|
||||
this.description = description;
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
21
ArgumentBase/IsVariableAttribute.cs
Normal file
21
ArgumentBase/IsVariableAttribute.cs
Normal file
@ -0,0 +1,21 @@
|
||||
using System;
|
||||
|
||||
namespace ArgumentBase;
|
||||
|
||||
[AttributeUsage(AttributeTargets.Property)]
|
||||
public class IsVariableAttribute : Attribute
|
||||
{
|
||||
public readonly string description;
|
||||
public readonly string? name;
|
||||
|
||||
public IsVariableAttribute(string description)
|
||||
{
|
||||
this.description = description;
|
||||
name = null;
|
||||
}
|
||||
public IsVariableAttribute(string name, string description)
|
||||
{
|
||||
this.description = description;
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
48
ArgumentBase/PrintHelper.cs
Normal file
48
ArgumentBase/PrintHelper.cs
Normal file
@ -0,0 +1,48 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
|
||||
namespace ArgumentBase;
|
||||
|
||||
internal static class PrintHelper
|
||||
{
|
||||
public static void PrintKeyValues(string title, int indent, Dictionary<string, string> values,
|
||||
string? keyFormat = null, string? separatorFormat = null, string? valueFormat = null)
|
||||
{
|
||||
StringBuilder result = new();
|
||||
result.Append($"{new string(' ', indent)}\x1b[1;97m{title}:\x1b[22m\n");
|
||||
|
||||
int maxLength = 0;
|
||||
StringBuilder[] lines = new StringBuilder[values.Count];
|
||||
IEnumerator<KeyValuePair<string, string>> iterator = values.GetEnumerator();
|
||||
for (int i = 0; i < values.Count; i++)
|
||||
{
|
||||
iterator.MoveNext();
|
||||
KeyValuePair<string, string> kv = iterator.Current;
|
||||
lines[i] = new StringBuilder().Append($"{new string(' ', indent + 2)}{keyFormat ?? "\x1b[90m"}{kv.Key}");
|
||||
|
||||
int rawKeyLength = visibleStringLength(kv.Key);
|
||||
if (rawKeyLength > maxLength) maxLength = kv.Key.Length;
|
||||
}
|
||||
|
||||
int desired = maxLength + 2;
|
||||
iterator.Reset();
|
||||
for (int i = 0; i < values.Count; i++)
|
||||
{
|
||||
iterator.MoveNext();
|
||||
KeyValuePair<string, string> kv = iterator.Current;
|
||||
int rawKeyLength = visibleStringLength(kv.Key);
|
||||
int remaining = desired - rawKeyLength;
|
||||
|
||||
lines[i].Append($"{new string(' ', remaining)}{separatorFormat ?? "\x1b[91m- "}{valueFormat ?? "\x1b[37m"}{kv.Value}\x1b[0m");
|
||||
result.Append(lines[i]);
|
||||
result.AppendLine();
|
||||
}
|
||||
Console.WriteLine(result);
|
||||
|
||||
static int visibleStringLength(string str) => str.ToCharArray().Where(x => !char.IsControl(x)).Count();
|
||||
}
|
||||
}
|
||||
38
README.md
Normal file
38
README.md
Normal file
@ -0,0 +1,38 @@
|
||||
# ArgumentBase
|
||||
|
||||
This is a small library that will parse your command-line arguments for you in a pretty easy-to-use fashion.
|
||||
This library only exists because I wrote this code for a different project and then found myself copy-pasting
|
||||
it constantly. This is to ease my own suffering.
|
||||
|
||||
This is largely purpose-built for me, but feel free to use it. That's why it's here.
|
||||
|
||||
## How to use
|
||||
|
||||
Import the package using your preferred method. Then, once it's installed, create a class like this:
|
||||
```csharp
|
||||
public class YourArguments : ArgumentBase<YourArguments>
|
||||
{
|
||||
// Positional arguments are called "parameters." No prefix is necessary.
|
||||
[IsParameter(1, "An example description for the parameter.")]
|
||||
public string ExampleParameter { get; set; } // It must be a property with a set method or it won't be identified.
|
||||
|
||||
// Variables are formatted like this: "-var:3.14"
|
||||
[IsVariable("var", "An example description for the variable.")]
|
||||
public double ExampleVariable { get; set; } // Parameters and variables can be any object that derives from IParsable.
|
||||
|
||||
// Flags are formatted like this: "--flag"
|
||||
[IsFlag("flag", "An example description for the flag.")]
|
||||
public bool ExampleFlag { get; set; } // Flags, however, can only be booleans.
|
||||
// Whenever a flag is included as an argument, its value is flipped.
|
||||
}
|
||||
```
|
||||
|
||||
Then, in your Main method, paste the following:
|
||||
```csharp
|
||||
static void Main(string[] args)
|
||||
{
|
||||
YourArguments args = YourArguments.Parse(args);
|
||||
}
|
||||
```
|
||||
|
||||
That's it. Not too bad, right?
|
||||
Loading…
x
Reference in New Issue
Block a user