ConsoleRunner.cs 2.5 KB

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