wabbajack/Wabbajack.CLI.Builder/CommandLineBuilder.cs

113 lines
3.4 KiB
C#
Raw Normal View History

2021-09-27 12:42:46 +00:00
using System.CommandLine;
using System.CommandLine.Builder;
2022-10-01 01:58:54 +00:00
using System.CommandLine.Invocation;
using System.CommandLine.NamingConventionBinder;
2022-10-01 00:46:15 +00:00
using Microsoft.Extensions.DependencyInjection;
2022-10-01 01:58:54 +00:00
using Wabbajack.Paths;
2021-09-27 12:42:46 +00:00
namespace Wabbajack.CLI.Builder;
2021-10-23 16:51:17 +00:00
public class CommandLineBuilder
2021-09-27 12:42:46 +00:00
{
2022-10-01 01:58:54 +00:00
private static IServiceProvider _provider;
2022-10-14 22:46:38 +00:00
public CommandLineBuilder(IServiceProvider provider)
2021-10-23 16:51:17 +00:00
{
2022-10-01 01:58:54 +00:00
_provider = provider;
2021-10-23 16:51:17 +00:00
}
2021-10-23 16:51:17 +00:00
public async Task<int> Run(string[] args)
{
var root = new RootCommand();
2022-10-01 01:58:54 +00:00
foreach (var verb in _commands)
{
root.Add(MakeCommend(verb.Type, verb.Handler, verb.Definition));
}
2021-10-23 16:51:17 +00:00
return await root.InvokeAsync(args);
2021-09-27 12:42:46 +00:00
}
2022-10-01 00:46:15 +00:00
2022-10-01 01:58:54 +00:00
private static Dictionary<Type, Func<OptionDefinition, Option>> _optionCtors = new()
{
{
typeof(string),
d => new Option<string>(d.Aliases, description: d.Description)
},
{
typeof(AbsolutePath),
d => new Option<AbsolutePath>(d.Aliases, description: d.Description, parseArgument: d => d.Tokens.Single().Value.ToAbsolutePath())
},
{
typeof(Uri),
d => new Option<Uri>(d.Aliases, description: d.Description)
},
{
typeof(bool),
d => new Option<bool>(d.Aliases, description: d.Description)
},
};
private Command MakeCommend(Type verbType, Func<object, Delegate> verbHandler, VerbDefinition definition)
2022-10-01 01:58:54 +00:00
{
var command = new Command(definition.Name, definition.Description);
foreach (var option in definition.Options)
{
command.Add(_optionCtors[option.Type](option));
}
command.Handler = new HandlerDelegate(_provider, verbType, verbHandler);
return command;
}
private class HandlerDelegate : ICommandHandler
{
private IServiceProvider _provider;
private Type _type;
private readonly Func<object, Delegate> _delgate;
2022-10-01 01:58:54 +00:00
public HandlerDelegate(IServiceProvider provider, Type type, Func<object, Delegate> inner)
2022-10-01 01:58:54 +00:00
{
_provider = provider;
_type = type;
_delgate = inner;
}
public int Invoke(InvocationContext context)
{
var service = _provider.GetRequiredService(_type);
2022-10-01 01:58:54 +00:00
var handler = CommandHandler.Create(_delgate(service));
return handler.Invoke(context);
}
public Task<int> InvokeAsync(InvocationContext context)
{
var service = _provider.GetRequiredService(_type);
2022-10-01 01:58:54 +00:00
var handler = CommandHandler.Create(_delgate(service));
return handler.InvokeAsync(context);
}
}
private static List<(Type Type, VerbDefinition Definition, Func<object, Delegate> Handler)> _commands { get; set; } = new();
2022-10-01 01:35:36 +00:00
public static IEnumerable<Type> Verbs => _commands.Select(c => c.Type);
public static void RegisterCommand<T>(VerbDefinition definition, Func<object, Delegate> handler)
2022-10-01 00:46:15 +00:00
{
2022-10-01 01:35:36 +00:00
_commands.Add((typeof(T), definition, handler));
2022-10-01 00:46:15 +00:00
}
}
2022-10-01 01:58:54 +00:00
public record OptionDefinition(Type Type, string ShortOption, string LongOption, string Description)
{
public string[] Aliases
{
get
{
return new[] { "-" + ShortOption, "--" + LongOption };
}
}
}
2022-10-01 00:46:15 +00:00
2022-10-01 01:35:36 +00:00
public record VerbDefinition(string Name, string Description, OptionDefinition[] Options)
2022-10-01 00:46:15 +00:00
{
}