wabbajack/Wabbajack.CLI/CommandLineBuilder.cs

136 lines
4.0 KiB
C#
Raw Normal View History

2022-10-01 00:46:15 +00:00
using System;
2021-09-27 12:42:46 +00:00
using System.Collections.Generic;
using System.CommandLine;
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 System.ComponentModel.Design;
using System.Linq;
2021-09-27 12:42:46 +00:00
using System.Threading.Tasks;
2022-10-01 00:46:15 +00:00
using Microsoft.Extensions.DependencyInjection;
2021-09-27 12:42:46 +00:00
using Wabbajack.CLI.Verbs;
2022-10-01 01:58:54 +00:00
using Wabbajack.Paths;
2021-09-27 12:42:46 +00:00
using Wabbajack.Services.OSIntegrated;
2021-10-23 16:51:17 +00:00
namespace Wabbajack.CLI;
2022-10-01 00:46:15 +00:00
public partial class CommandLineBuilder
2021-09-27 12:42:46 +00:00
{
2022-10-01 01:58:54 +00:00
private static IServiceProvider _provider;
public CommandLineBuilder(IServiceProvider provider, IConsole console, LoggingRateLimiterReporter _)
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-09-27 12:42:46 +00:00
2022-10-01 00:46:15 +00:00
static CommandLineBuilder()
{
RegisterAll();
}
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<IVerb, Delegate> verbHandler, VerbDefinition definition)
{
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<IVerb, Delegate> _delgate;
public HandlerDelegate(IServiceProvider provider, Type type, Func<IVerb, Delegate> inner)
{
_provider = provider;
_type = type;
_delgate = inner;
}
public int Invoke(InvocationContext context)
{
var service = (IVerb)_provider.GetRequiredService(_type);
var handler = CommandHandler.Create(_delgate(service));
return handler.Invoke(context);
}
public Task<int> InvokeAsync(InvocationContext context)
{
var service = (IVerb)_provider.GetRequiredService(_type);
var handler = CommandHandler.Create(_delgate(service));
return handler.InvokeAsync(context);
}
}
2022-10-01 01:35:36 +00:00
private static List<(Type Type, VerbDefinition Definition, Func<IVerb, Delegate> Handler)> _commands { get; set; } = new();
public static IEnumerable<Type> Verbs => _commands.Select(c => c.Type);
public static void RegisterCommand<T>(VerbDefinition definition, Func<IVerb, 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
{
}
public static class CommandLineBuilderExtensions
{
public static IServiceCollection AddCommands(this IServiceCollection services)
{
services.AddSingleton<CommandLineBuilder>();
foreach (var verb in CommandLineBuilder.Verbs)
{
2022-10-01 01:58:54 +00:00
services.AddSingleton(verb);
2022-10-01 00:46:15 +00:00
}
return services;
}
2021-09-27 12:42:46 +00:00
}