ConsoleRunner.cs 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. using RackPeek.Domain;
  2. using Spectre.Console;
  3. using Spectre.Console.Cli;
  4. using Spectre.Console.Testing;
  5. namespace Shared.Rcl;
  6. public class ConsoleEmulator : IConsoleEmulator {
  7. public ConsoleEmulator(IServiceProvider provider) {
  8. var registrar = new TypeRegistrar(provider);
  9. App = new CommandApp(registrar);
  10. CliBootstrap.BuildApp(App);
  11. }
  12. public CommandApp App { get; }
  13. public async Task<string> Execute(string input) {
  14. var testConsole = new TestConsole();
  15. testConsole.Width(120);
  16. AnsiConsole.Console = testConsole;
  17. App.Configure(c => c.Settings.Console = testConsole);
  18. await App.RunAsync(ParseArguments(input));
  19. return testConsole.Output;
  20. }
  21. internal static string[] ParseArguments(string input) {
  22. var args = new List<string>();
  23. var current = new System.Text.StringBuilder();
  24. char? quote = null;
  25. for (var i = 0; i < input.Length; i++) {
  26. var c = input[i];
  27. if (quote.HasValue) {
  28. if (c == quote.Value)
  29. quote = null;
  30. else
  31. current.Append(c);
  32. }
  33. else if (c is '"' or '\'') {
  34. quote = c;
  35. }
  36. else if (c == ' ') {
  37. if (current.Length > 0) {
  38. args.Add(current.ToString());
  39. current.Clear();
  40. }
  41. }
  42. else {
  43. current.Append(c);
  44. }
  45. }
  46. if (current.Length > 0)
  47. args.Add(current.ToString());
  48. return args.ToArray();
  49. }
  50. }
  51. public sealed class TypeRegistrar : ITypeRegistrar {
  52. private readonly IServiceProvider _provider;
  53. public TypeRegistrar(IServiceProvider provider) {
  54. _provider = provider;
  55. }
  56. public void Register(Type service, Type implementation) {
  57. // DO NOTHING — services must already be registered
  58. }
  59. public void RegisterInstance(Type service, object implementation) {
  60. // DO NOTHING
  61. }
  62. public void RegisterLazy(Type service, Func<object> factory) {
  63. // DO NOTHING
  64. }
  65. public ITypeResolver Build() => new TypeResolver(_provider);
  66. }
  67. public sealed class TypeResolver : ITypeResolver {
  68. private readonly IServiceProvider _provider;
  69. public TypeResolver(IServiceProvider provider) {
  70. _provider = provider;
  71. }
  72. public object? Resolve(Type? type) => type == null ? null : _provider.GetService(type);
  73. }