spectre.console
spectre.console copied to clipboard
Allow AnsiConsoleFactory to use a user provided IAnsiConsoleInput
Is Your Feature Request Related to a Problem? Please Describe.
I've encountered an issue where I am unable to bind my input back to the IAnsiConsole when utilizing AnsiConsoleFactory. My application is a Blazor app, meaning the input mechanism I employ does not originate from StandardInput. Instead, it's an adaptation of browser-sourced keyboard events.
Describe the Solution You'd Like
I propose the introduction of the ability to provide a custom implementation of IAnsiConsoleInput through a property in AnsiConsoleSettings. This adjustment would enable the construction of my console using AnsiConsoleFactory, allowing for more flexibility and integration with my Blazor application.
Describe Alternatives You've Considered
Initially, I attempted to develop my own version of AnsiConsoleFactory. However, I quickly discovered a complex chain of dependencies among classes designated as internal, which significantly hampers the practicality of leveraging the extensive utility offered by the built-in AnsiConsoleFactory.
Additional Context
I discovered that with a few minor modifications, it was possible to integrate my custom input in a manner that is fully backward compatible.
Here is the approach I took: https://github.com/Astn/spectre.console/commit/68fc35d99710e4dd9aada550dc781adb95f0164f
Subject: [PATCH] Allow ConsoleInput to be passed in.
---
Index: src/Spectre.Console/AnsiConsoleFactory.cs
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/src/Spectre.Console/AnsiConsoleFactory.cs b/src/Spectre.Console/AnsiConsoleFactory.cs
--- a/src/Spectre.Console/AnsiConsoleFactory.cs (revision 8da05bcc176741565ddace97bcc59f58587734eb)
+++ b/src/Spectre.Console/AnsiConsoleFactory.cs (revision 68fc35d99710e4dd9aada550dc781adb95f0164f)
@@ -59,9 +59,15 @@
settings.Enrichment,
settings.EnvironmentVariables);
- return new AnsiConsoleFacade(
+ settings.InputBuilder ??= (p) => new DefaultInput(p);
+ settings.Input ??= settings.InputBuilder(profile);
+ settings.ExclusivityMode ??= new DefaultExclusivityMode();
+ var acf = new AnsiConsoleFacade(
profile,
- settings.ExclusivityMode ?? new DefaultExclusivityMode());
+ settings.ExclusivityMode,
+ settings.Input);
+
+ return acf;
}
private static (bool Ansi, bool Legacy) DetectAnsi(AnsiConsoleSettings settings, System.IO.TextWriter buffer)
Index: src/Spectre.Console/AnsiConsoleSettings.cs
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/src/Spectre.Console/AnsiConsoleSettings.cs b/src/Spectre.Console/AnsiConsoleSettings.cs
--- a/src/Spectre.Console/AnsiConsoleSettings.cs (revision 8da05bcc176741565ddace97bcc59f58587734eb)
+++ b/src/Spectre.Console/AnsiConsoleSettings.cs (revision 68fc35d99710e4dd9aada550dc781adb95f0164f)
@@ -21,6 +21,13 @@
/// </summary>
public IAnsiConsoleOutput? Out { get; set; }
+
+ public Func<Profile, IAnsiConsoleInput>? InputBuilder { get; set; }
+ /// <summary>
+ /// Gets or sets the input.
+ /// </summary>
+ public IAnsiConsoleInput? Input { get; set; }
+
/// <summary>
/// Gets or sets a value indicating whether or not the
/// terminal is interactive or not.
Index: src/Spectre.Console/Internal/Backends/AnsiConsoleFacade.cs
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/src/Spectre.Console/Internal/Backends/AnsiConsoleFacade.cs b/src/Spectre.Console/Internal/Backends/AnsiConsoleFacade.cs
--- a/src/Spectre.Console/Internal/Backends/AnsiConsoleFacade.cs (revision 8da05bcc176741565ddace97bcc59f58587734eb)
+++ b/src/Spectre.Console/Internal/Backends/AnsiConsoleFacade.cs (revision 68fc35d99710e4dd9aada550dc781adb95f0164f)
@@ -12,12 +12,12 @@
public IExclusivityMode ExclusivityMode { get; }
public RenderPipeline Pipeline { get; }
- public AnsiConsoleFacade(Profile profile, IExclusivityMode exclusivityMode)
+ public AnsiConsoleFacade(Profile profile, IExclusivityMode exclusivityMode, IAnsiConsoleInput input)
{
_renderLock = new object();
Profile = profile ?? throw new ArgumentNullException(nameof(profile));
- Input = new DefaultInput(Profile);
+ Input = input;
ExclusivityMode = exclusivityMode ?? throw new ArgumentNullException(nameof(exclusivityMode));
Pipeline = new RenderPipeline();
Thoughts?
Please upvote :+1: this issue if you are interested in it.
few years back I went down this route when I wanted to try and see what running spectre.console in blazor would look like. I came up with a pretty similar solution to this with a fork and it worked well. I'd be in favor
here's that repo for what its worth - https://github.com/phil-scott-78/try-spectre/blob/main/src/TrySpectre/Pages/Index.razor