Files
spectre.console/src/Spectre.Console/Live/Status/Status.cs
Patrik Svensson 52c1d9122b Add global usings (#668)
* Use global usings

* Fix namespace declarations for test projects
2021-12-23 16:50:31 +01:00

123 lines
3.8 KiB
C#

namespace Spectre.Console;
/// <summary>
/// Represents a status display.
/// </summary>
public sealed class Status
{
private readonly IAnsiConsole _console;
/// <summary>
/// Gets or sets the spinner.
/// </summary>
public Spinner? Spinner { get; set; }
/// <summary>
/// Gets or sets the spinner style.
/// </summary>
public Style? SpinnerStyle { get; set; } = new Style(foreground: Color.Yellow);
/// <summary>
/// Gets or sets a value indicating whether or not status
/// should auto refresh. Defaults to <c>true</c>.
/// </summary>
public bool AutoRefresh { get; set; } = true;
/// <summary>
/// Initializes a new instance of the <see cref="Status"/> class.
/// </summary>
/// <param name="console">The console.</param>
public Status(IAnsiConsole console)
{
_console = console ?? throw new ArgumentNullException(nameof(console));
}
/// <summary>
/// Starts a new status display.
/// </summary>
/// <param name="status">The status to display.</param>
/// <param name="action">The action to execute.</param>
public void Start(string status, Action<StatusContext> action)
{
var task = StartAsync(status, ctx =>
{
action(ctx);
return Task.CompletedTask;
});
task.GetAwaiter().GetResult();
}
/// <summary>
/// Starts a new status display.
/// </summary>
/// <typeparam name="T">The result type.</typeparam>
/// <param name="status">The status to display.</param>
/// <param name="func">The action to execute.</param>
/// <returns>The result.</returns>
public T Start<T>(string status, Func<StatusContext, T> func)
{
var task = StartAsync(status, ctx => Task.FromResult(func(ctx)));
return task.GetAwaiter().GetResult();
}
/// <summary>
/// Starts a new status display.
/// </summary>
/// <param name="status">The status to display.</param>
/// <param name="action">The action to execute.</param>
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
public async Task StartAsync(string status, Func<StatusContext, Task> action)
{
if (action is null)
{
throw new ArgumentNullException(nameof(action));
}
_ = await StartAsync<object?>(status, async statusContext =>
{
await action(statusContext).ConfigureAwait(false);
return default;
}).ConfigureAwait(false);
}
/// <summary>
/// Starts a new status display and returns a result.
/// </summary>
/// <typeparam name="T">The result type of task.</typeparam>
/// <param name="status">The status to display.</param>
/// <param name="func">The action to execute.</param>
/// <returns>A <see cref="Task{T}"/> representing the asynchronous operation.</returns>
public async Task<T> StartAsync<T>(string status, Func<StatusContext, Task<T>> func)
{
if (func is null)
{
throw new ArgumentNullException(nameof(func));
}
// Set the progress columns
var spinnerColumn = new SpinnerColumn(Spinner ?? Spinner.Known.Default)
{
Style = SpinnerStyle ?? Style.Plain,
};
var progress = new Progress(_console)
{
FallbackRenderer = new FallbackStatusRenderer(),
AutoClear = true,
AutoRefresh = AutoRefresh,
};
progress.Columns(new ProgressColumn[]
{
spinnerColumn,
new TaskDescriptionColumn(),
});
return await progress.StartAsync(async ctx =>
{
var statusContext = new StatusContext(ctx, ctx.AddTask(status), spinnerColumn);
return await func(statusContext).ConfigureAwait(false);
}).ConfigureAwait(false);
}
}