Open rafaelsc opened 8 months ago
Proof of concept. (Only for the progress bar, title bar update still need some work)
https://github.com/spectreconsole/spectre.console/assets/502282/1b5f5b21-037c-49f9-a363-d5c9bb2240cd
Code:
using Spectre.Console;
using Spectre.Console.Rendering;
Console.CancelKeyPress += (_, _) => TerminalProgressUpdater.Clear();
var progress = AnsiConsole.Progress();
progress.RenderHook = Render;
await progress.StartAsync(async ctx =>
{
var task1 = ctx.AddTask("[green]Reticulating splines[/]");
var task2 = ctx.AddTask("[green]Folding space[/]");
while (task1.Percentage < 50)
{
await Task.Delay(200);
task1.Increment(1.5);
task2.Increment(1);
}
var task3 = ctx.AddTask("[red]New Challenger[/]");
while (!ctx.IsFinished)
{
await Task.Delay(100);
task1.Increment(1.75);
task2.Increment(1);
task3.Increment(2);
}
});
static IRenderable Render(IRenderable renderable, IReadOnlyList<ProgressTask> tasks)
{
TerminalProgressUpdater.Update(tasks);
return renderable;
}
internal static class TerminalProgressUpdater
{
public static void Start() => AnsiConsole.Write(Ansi.Progress(State.Indeterminate, 0));
public static void Indeterminate() => AnsiConsole.Write(Ansi.Progress(State.Indeterminate, 0));
public static void Update(byte progress)
{
ArgumentOutOfRangeException.ThrowIfGreaterThan(progress, 100);
AnsiConsole.Write(Ansi.Progress(State.Default, progress));
}
public static void Update(IReadOnlyList<ProgressTask> tasks)
{
ArgumentNullException.ThrowIfNull(tasks);
if (tasks.Count == 0)
{
Finished();
return;
}
var IsFinished = tasks.Where(x => x.IsStarted).All(task => task.IsFinished);
if (IsFinished)
{
Finished();
return;
}
var isIndeterminate = tasks.Any(x => x.IsIndeterminate);
if (isIndeterminate)
{
Indeterminate();
return;
}
var allProgress = tasks.Sum(x => x.Percentage);
var progress = (byte)(allProgress / tasks.Count);
Update(progress);
}
public static void Finished() => AnsiConsole.Write(Ansi.Progress(State.Hidden, 0));
public static void Clear() => AnsiConsole.Write(Ansi.Progress(State.Hidden, 0));
private static class Ansi
{
public const string ESC = "\u001b";
public const string BEL = "\u0007";
public static string Progress(State state, byte progress) => $"{ESC}]9;4;{(byte)state};{progress}{BEL}";
}
private enum State
{
Hidden = 0,
Default = 1,
Error = 2,
Indeterminate = 3,
Warning = 4,
}
}
Spectre console is lacking integration with Operation System and Terminal progress Indication/feedback. And would be a nice to have feature, improving the feedback of the progress to the User.
Describe the solution you'd like Any Progress or group of Progress update in Spectre console, update the Terminal Progress too.
Additional context
Please upvote :+1: this issue if you are interested in it.