mirror of
https://github.com/nsnail/spectre.console.git
synced 2025-04-16 08:52:50 +08:00
Add support for exclusive mode
This commit is contained in:
parent
c2bab0ebf8
commit
7f6f2437b1
12
docs/input/live/index.cshtml
Normal file
12
docs/input/live/index.cshtml
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
Title: Live Displays
|
||||||
|
Order: 4
|
||||||
|
---
|
||||||
|
|
||||||
|
<h1>Sections</h1>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
@foreach (IDocument child in OutputPages.GetChildrenOf(Document))
|
||||||
|
{
|
||||||
|
<li>@Html.DocumentLink(child)</li>
|
||||||
|
}
|
||||||
|
</ul>
|
@ -1,16 +1,23 @@
|
|||||||
Title: Progress
|
Title: Progress
|
||||||
Order: 5
|
Order: 5
|
||||||
|
RedirectFrom: progress
|
||||||
---
|
---
|
||||||
|
|
||||||
Spectre.Console can display information about long running tasks in the console.
|
Spectre.Console can display information about long running tasks in the console.
|
||||||
|
|
||||||
<img src="assets/images/progress.png" style="max-width: 100%;margin-bottom:20px;">
|
<img src="../assets/images/progress.png" style="max-width: 100%;margin-bottom:20px;">
|
||||||
|
|
||||||
|
<div class="alert alert-warning" role="alert">
|
||||||
|
<i class="fas fa-exclamation-triangle icon-web"></i> The progress display is not
|
||||||
|
thread safe, and using it together with other interactive components such as
|
||||||
|
prompts, status displays or other progress displays are not supported.
|
||||||
|
</div>
|
||||||
|
|
||||||
If the current terminal isn't considered "interactive", such as when running
|
If the current terminal isn't considered "interactive", such as when running
|
||||||
in a continuous integration system, or the terminal can't display
|
in a continuous integration system, or the terminal can't display
|
||||||
ANSI control sequence, any progress will be displayed in a simpler way.
|
ANSI control sequence, any progress will be displayed in a simpler way.
|
||||||
|
|
||||||
<img src="assets/images/progress_fallback.png" style="max-width: 100%;">
|
<img src="../assets/images/progress_fallback.png" style="max-width: 100%;">
|
||||||
|
|
||||||
# Usage
|
# Usage
|
||||||
|
|
@ -1,10 +1,17 @@
|
|||||||
Title: Status
|
Title: Status
|
||||||
Order: 6
|
Order: 6
|
||||||
|
RedirectFrom: status
|
||||||
---
|
---
|
||||||
|
|
||||||
Spectre.Console can display information about long running tasks in the console.
|
Spectre.Console can display information about long running tasks in the console.
|
||||||
|
|
||||||
<img src="assets/images/status.gif" style="max-width: 100%;margin-bottom:20px;">
|
<img src="../assets/images/status.gif" style="max-width: 100%;margin-bottom:20px;">
|
||||||
|
|
||||||
|
<div class="alert alert-warning" role="alert">
|
||||||
|
<i class="fas fa-exclamation-triangle icon-web"></i> The status display is not
|
||||||
|
thread safe, and using it together with other interactive components such as
|
||||||
|
prompts, progress displays or other status displays are not supported.
|
||||||
|
</div>
|
||||||
|
|
||||||
If the current terminal isn't considered "interactive", such as when running
|
If the current terminal isn't considered "interactive", such as when running
|
||||||
in a continuous integration system, or the terminal can't display
|
in a continuous integration system, or the terminal can't display
|
@ -7,6 +7,11 @@ one or many items from a provided list.
|
|||||||
|
|
||||||
<img src="../assets/images/multiselection.gif" style="width: 100%;" />
|
<img src="../assets/images/multiselection.gif" style="width: 100%;" />
|
||||||
|
|
||||||
|
<div class="alert alert-warning" role="alert" style="margin-top:20px;">
|
||||||
|
<i class="fas fa-exclamation-triangle icon-web"></i> The use of prompts
|
||||||
|
insides status or progress displays is not supported.
|
||||||
|
</div>
|
||||||
|
|
||||||
# Usage
|
# Usage
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
|
@ -7,6 +7,11 @@ a single item from a provided list.
|
|||||||
|
|
||||||
<img src="../assets/images/selection.gif" style="width: 100%;" />
|
<img src="../assets/images/selection.gif" style="width: 100%;" />
|
||||||
|
|
||||||
|
<div class="alert alert-warning" role="alert" style="margin-top:20px;">
|
||||||
|
<i class="fas fa-exclamation-triangle icon-web"></i> Using prompts inside
|
||||||
|
status or progress displays, are not supported.
|
||||||
|
</div>
|
||||||
|
|
||||||
# Usage
|
# Usage
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
Title: Text
|
Title: Text prompt
|
||||||
Order: 0
|
Order: 0
|
||||||
RedirectFrom: prompt
|
RedirectFrom: prompt
|
||||||
---
|
---
|
||||||
@ -6,6 +6,11 @@ RedirectFrom: prompt
|
|||||||
Sometimes you want to get some input from the user, and for this
|
Sometimes you want to get some input from the user, and for this
|
||||||
you can use the `Prompt<TResult>`.
|
you can use the `Prompt<TResult>`.
|
||||||
|
|
||||||
|
<div class="alert alert-warning" role="alert">
|
||||||
|
<i class="fas fa-exclamation-triangle icon-web"></i> The use of prompts
|
||||||
|
insides status or progress displays is not supported.
|
||||||
|
</div>
|
||||||
|
|
||||||
# Confirmation
|
# Confirmation
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
"isRoot": true,
|
"isRoot": true,
|
||||||
"tools": {
|
"tools": {
|
||||||
"cake.tool": {
|
"cake.tool": {
|
||||||
"version": "1.0.0-rc0002",
|
"version": "1.1.0",
|
||||||
"commands": [
|
"commands": [
|
||||||
"dotnet-cake"
|
"dotnet-cake"
|
||||||
]
|
]
|
||||||
|
@ -59,6 +59,7 @@ namespace Cursor
|
|||||||
new MultiSelectionPrompt<string>()
|
new MultiSelectionPrompt<string>()
|
||||||
.PageSize(10)
|
.PageSize(10)
|
||||||
.Title("What are your [green]favorite fruits[/]?")
|
.Title("What are your [green]favorite fruits[/]?")
|
||||||
|
.MoreChoicesText("[grey](Move up and down to reveal more fruits)[/]")
|
||||||
.InstructionsText("[grey](Press [blue]<space>[/] to toggle a fruit, [green]<enter>[/] to accept)[/]")
|
.InstructionsText("[grey](Press [blue]<space>[/] to toggle a fruit, [green]<enter>[/] to accept)[/]")
|
||||||
.AddChoices(new[]
|
.AddChoices(new[]
|
||||||
{
|
{
|
||||||
@ -75,6 +76,7 @@ namespace Cursor
|
|||||||
fruit = AnsiConsole.Prompt(
|
fruit = AnsiConsole.Prompt(
|
||||||
new SelectionPrompt<string>()
|
new SelectionPrompt<string>()
|
||||||
.Title("Ok, but if you could only choose [green]one[/]?")
|
.Title("Ok, but if you could only choose [green]one[/]?")
|
||||||
|
.MoreChoicesText("[grey](Move up and down to reveal more fruits)[/]")
|
||||||
.AddChoices(favorites));
|
.AddChoices(favorites));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,12 +9,14 @@ namespace Spectre.Console.Testing
|
|||||||
{
|
{
|
||||||
private readonly StringWriter _writer;
|
private readonly StringWriter _writer;
|
||||||
private readonly IAnsiConsole _console;
|
private readonly IAnsiConsole _console;
|
||||||
|
private readonly FakeExclusivityMode _exclusivityLock;
|
||||||
|
|
||||||
public string Output => _writer.ToString();
|
public string Output => _writer.ToString();
|
||||||
|
|
||||||
public Profile Profile => _console.Profile;
|
public Profile Profile => _console.Profile;
|
||||||
public IAnsiConsoleCursor Cursor => _console.Cursor;
|
public IAnsiConsoleCursor Cursor => _console.Cursor;
|
||||||
public FakeConsoleInput Input { get; }
|
public FakeConsoleInput Input { get; }
|
||||||
|
public IExclusivityMode ExclusivityMode => _exclusivityLock;
|
||||||
public RenderPipeline Pipeline => _console.Pipeline;
|
public RenderPipeline Pipeline => _console.Pipeline;
|
||||||
|
|
||||||
IAnsiConsoleInput IAnsiConsole.Input => Input;
|
IAnsiConsoleInput IAnsiConsole.Input => Input;
|
||||||
@ -24,6 +26,7 @@ namespace Spectre.Console.Testing
|
|||||||
AnsiSupport ansi = AnsiSupport.Yes,
|
AnsiSupport ansi = AnsiSupport.Yes,
|
||||||
int width = 80)
|
int width = 80)
|
||||||
{
|
{
|
||||||
|
_exclusivityLock = new FakeExclusivityMode();
|
||||||
_writer = new StringWriter();
|
_writer = new StringWriter();
|
||||||
|
|
||||||
var factory = new AnsiConsoleFactory();
|
var factory = new AnsiConsoleFactory();
|
||||||
|
@ -12,6 +12,7 @@ namespace Spectre.Console.Testing
|
|||||||
public Profile Profile { get; }
|
public Profile Profile { get; }
|
||||||
public IAnsiConsoleCursor Cursor => new FakeAnsiConsoleCursor();
|
public IAnsiConsoleCursor Cursor => new FakeAnsiConsoleCursor();
|
||||||
IAnsiConsoleInput IAnsiConsole.Input => Input;
|
IAnsiConsoleInput IAnsiConsole.Input => Input;
|
||||||
|
public IExclusivityMode ExclusivityMode { get; }
|
||||||
public RenderPipeline Pipeline { get; }
|
public RenderPipeline Pipeline { get; }
|
||||||
|
|
||||||
public FakeConsoleInput Input { get; }
|
public FakeConsoleInput Input { get; }
|
||||||
@ -24,6 +25,7 @@ namespace Spectre.Console.Testing
|
|||||||
bool legacyConsole = false, bool interactive = true)
|
bool legacyConsole = false, bool interactive = true)
|
||||||
{
|
{
|
||||||
Input = new FakeConsoleInput();
|
Input = new FakeConsoleInput();
|
||||||
|
ExclusivityMode = new FakeExclusivityMode();
|
||||||
Pipeline = new RenderPipeline();
|
Pipeline = new RenderPipeline();
|
||||||
|
|
||||||
Profile = new Profile(new StringWriter(), encoding ?? Encoding.UTF8);
|
Profile = new Profile(new StringWriter(), encoding ?? Encoding.UTF8);
|
||||||
|
18
src/Spectre.Console.Testing/Fakes/FakeExclusivityMode.cs
Normal file
18
src/Spectre.Console.Testing/Fakes/FakeExclusivityMode.cs
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Spectre.Console.Testing
|
||||||
|
{
|
||||||
|
public sealed class FakeExclusivityMode : IExclusivityMode
|
||||||
|
{
|
||||||
|
public T Run<T>(Func<T> func)
|
||||||
|
{
|
||||||
|
return func();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<T> Run<T>(Func<Task<T>> func)
|
||||||
|
{
|
||||||
|
return await func();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -2,6 +2,7 @@ using System;
|
|||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using Spectre.Console.Enrichment;
|
using Spectre.Console.Enrichment;
|
||||||
|
using Spectre.Console.Internal;
|
||||||
|
|
||||||
namespace Spectre.Console
|
namespace Spectre.Console
|
||||||
{
|
{
|
||||||
@ -58,7 +59,9 @@ namespace Spectre.Console
|
|||||||
settings.Enrichment,
|
settings.Enrichment,
|
||||||
settings.EnvironmentVariables);
|
settings.EnvironmentVariables);
|
||||||
|
|
||||||
return new AnsiConsoleFacade(profile);
|
return new AnsiConsoleFacade(
|
||||||
|
profile,
|
||||||
|
settings.ExclusivityMode ?? new DefaultExclusivityMode());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static (bool Ansi, bool Legacy) DetectAnsi(AnsiConsoleSettings settings, System.IO.TextWriter buffer)
|
private static (bool Ansi, bool Legacy) DetectAnsi(AnsiConsoleSettings settings, System.IO.TextWriter buffer)
|
||||||
|
@ -30,6 +30,11 @@ namespace Spectre.Console
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public InteractionSupport Interactive { get; set; }
|
public InteractionSupport Interactive { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the exclusivity mode.
|
||||||
|
/// </summary>
|
||||||
|
public IExclusivityMode? ExclusivityMode { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the profile enrichments settings.
|
/// Gets or sets the profile enrichments settings.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -31,7 +31,9 @@ namespace Spectre.Console.Cli
|
|||||||
set
|
set
|
||||||
{
|
{
|
||||||
#pragma warning disable CS8601 // Possible null reference assignment.
|
#pragma warning disable CS8601 // Possible null reference assignment.
|
||||||
|
#pragma warning disable CS8600 // Converting null literal or possible null value to non-nullable type.
|
||||||
Value = (T)value;
|
Value = (T)value;
|
||||||
|
#pragma warning restore CS8600 // Converting null literal or possible null value to non-nullable type.
|
||||||
#pragma warning restore CS8601 // Possible null reference assignment.
|
#pragma warning restore CS8601 // Possible null reference assignment.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -165,7 +165,9 @@ namespace Spectre.Console.Cli
|
|||||||
if (pair.Key != null)
|
if (pair.Key != null)
|
||||||
{
|
{
|
||||||
#pragma warning disable CS8604 // Possible null reference argument of value.
|
#pragma warning disable CS8604 // Possible null reference argument of value.
|
||||||
|
#pragma warning disable CS8600 // Converting null literal or possible null value to non-nullable type.
|
||||||
Add((TKey)pair.Key, (TValue)pair.Value);
|
Add((TKey)pair.Key, (TValue)pair.Value);
|
||||||
|
#pragma warning restore CS8600 // Converting null literal or possible null value to non-nullable type.
|
||||||
#pragma warning restore CS8604 // Possible null reference argument of value.
|
#pragma warning restore CS8604 // Possible null reference argument of value.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,35 @@
|
|||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Spectre.Console
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Contains extension methods for <see cref="IAnsiConsole"/>.
|
||||||
|
/// </summary>
|
||||||
|
public static partial class AnsiConsoleExtensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Runs the specified function in exclusive mode.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">The result type.</typeparam>
|
||||||
|
/// <param name="console">The console.</param>
|
||||||
|
/// <param name="func">The func to run in exclusive mode.</param>
|
||||||
|
/// <returns>The result of the function.</returns>
|
||||||
|
public static T RunExclusive<T>(this IAnsiConsole console, Func<T> func)
|
||||||
|
{
|
||||||
|
return console.ExclusivityMode.Run(func);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Runs the specified function in exclusive mode asynchronously.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">The result type.</typeparam>
|
||||||
|
/// <param name="console">The console.</param>
|
||||||
|
/// <param name="func">The func to run in exclusive mode.</param>
|
||||||
|
/// <returns>The result of the function.</returns>
|
||||||
|
public static Task<T> RunExclusive<T>(this IAnsiConsole console, Func<Task<T>> func)
|
||||||
|
{
|
||||||
|
return console.ExclusivityMode.Run(func);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -23,6 +23,11 @@ namespace Spectre.Console
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
IAnsiConsoleInput Input { get; }
|
IAnsiConsoleInput Input { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the exclusivity mode.
|
||||||
|
/// </summary>
|
||||||
|
IExclusivityMode ExclusivityMode { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the render pipeline.
|
/// Gets the render pipeline.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
27
src/Spectre.Console/IExclusivityMode.cs
Normal file
27
src/Spectre.Console/IExclusivityMode.cs
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Spectre.Console
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents an exclusivity mode.
|
||||||
|
/// </summary>
|
||||||
|
public interface IExclusivityMode
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Runs the specified function in exclusive mode.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">The result type.</typeparam>
|
||||||
|
/// <param name="func">The func to run in exclusive mode.</param>
|
||||||
|
/// <returns>The result of the function.</returns>
|
||||||
|
T Run<T>(Func<T> func);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Runs the specified function in exclusive mode asynchronously.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">The result type.</typeparam>
|
||||||
|
/// <param name="func">The func to run in exclusive mode.</param>
|
||||||
|
/// <returns>The result of the function.</returns>
|
||||||
|
Task<T> Run<T>(Func<Task<T>> func);
|
||||||
|
}
|
||||||
|
}
|
@ -13,9 +13,10 @@ namespace Spectre.Console
|
|||||||
public Profile Profile { get; }
|
public Profile Profile { get; }
|
||||||
public IAnsiConsoleCursor Cursor => GetBackend().Cursor;
|
public IAnsiConsoleCursor Cursor => GetBackend().Cursor;
|
||||||
public IAnsiConsoleInput Input { get; }
|
public IAnsiConsoleInput Input { get; }
|
||||||
|
public IExclusivityMode ExclusivityMode { get; }
|
||||||
public RenderPipeline Pipeline { get; }
|
public RenderPipeline Pipeline { get; }
|
||||||
|
|
||||||
public AnsiConsoleFacade(Profile profile)
|
public AnsiConsoleFacade(Profile profile, IExclusivityMode exclusivityMode)
|
||||||
{
|
{
|
||||||
_renderLock = new object();
|
_renderLock = new object();
|
||||||
_ansiBackend = new AnsiConsoleBackend(profile);
|
_ansiBackend = new AnsiConsoleBackend(profile);
|
||||||
@ -23,6 +24,7 @@ namespace Spectre.Console
|
|||||||
|
|
||||||
Profile = profile ?? throw new ArgumentNullException(nameof(profile));
|
Profile = profile ?? throw new ArgumentNullException(nameof(profile));
|
||||||
Input = new DefaultInput(Profile);
|
Input = new DefaultInput(Profile);
|
||||||
|
ExclusivityMode = exclusivityMode ?? throw new ArgumentNullException(nameof(exclusivityMode));
|
||||||
Pipeline = new RenderPipeline();
|
Pipeline = new RenderPipeline();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
using System.Linq;
|
|
||||||
using Spectre.Console.Rendering;
|
using Spectre.Console.Rendering;
|
||||||
using Wcwidth;
|
using Wcwidth;
|
||||||
|
|
||||||
|
57
src/Spectre.Console/Internal/DefaultExclusivityMode.cs
Normal file
57
src/Spectre.Console/Internal/DefaultExclusivityMode.cs
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
using System;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Spectre.Console.Internal
|
||||||
|
{
|
||||||
|
internal sealed class DefaultExclusivityMode : IExclusivityMode
|
||||||
|
{
|
||||||
|
private static readonly SemaphoreSlim _semaphore;
|
||||||
|
|
||||||
|
static DefaultExclusivityMode()
|
||||||
|
{
|
||||||
|
_semaphore = new SemaphoreSlim(1, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public T Run<T>(Func<T> func)
|
||||||
|
{
|
||||||
|
// Try aquiring the exclusivity semaphore
|
||||||
|
if (!_semaphore.Wait(0))
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException(
|
||||||
|
"Trying to run one or more interactive functions concurrently. " +
|
||||||
|
"Operations with dynamic displays (e.g. a prompt and a progress display) " +
|
||||||
|
"cannot be running at the same time.");
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return func();
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_semaphore.Release(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<T> Run<T>(Func<Task<T>> func)
|
||||||
|
{
|
||||||
|
// Try aquiring the exclusivity semaphore
|
||||||
|
if (!await _semaphore.WaitAsync(0).ConfigureAwait(false))
|
||||||
|
{
|
||||||
|
// TODO: Need a better message here
|
||||||
|
throw new InvalidOperationException(
|
||||||
|
"Could not aquire the interactive semaphore");
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return await func();
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_semaphore.Release(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -23,6 +23,9 @@ namespace Spectre.Console
|
|||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public IAnsiConsoleInput Input => _console.Input;
|
public IAnsiConsoleInput Input => _console.Input;
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public IExclusivityMode ExclusivityMode => _console.ExclusivityMode;
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public RenderPipeline Pipeline => _console.Pipeline;
|
public RenderPipeline Pipeline => _console.Pipeline;
|
||||||
|
|
||||||
|
@ -118,6 +118,8 @@ namespace Spectre.Console
|
|||||||
throw new ArgumentNullException(nameof(action));
|
throw new ArgumentNullException(nameof(action));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return await _console.RunExclusive(async () =>
|
||||||
|
{
|
||||||
var renderer = CreateRenderer();
|
var renderer = CreateRenderer();
|
||||||
renderer.Started();
|
renderer.Started();
|
||||||
|
|
||||||
@ -150,6 +152,7 @@ namespace Spectre.Console
|
|||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
}).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ProgressRenderer CreateRenderer()
|
private ProgressRenderer CreateRenderer()
|
||||||
|
@ -72,6 +72,11 @@ namespace Spectre.Console
|
|||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public List<T> Show(IAnsiConsole console)
|
public List<T> Show(IAnsiConsole console)
|
||||||
{
|
{
|
||||||
|
if (console is null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(console));
|
||||||
|
}
|
||||||
|
|
||||||
if (!console.Profile.Capabilities.Interactive)
|
if (!console.Profile.Capabilities.Interactive)
|
||||||
{
|
{
|
||||||
throw new NotSupportedException(
|
throw new NotSupportedException(
|
||||||
@ -86,6 +91,8 @@ namespace Spectre.Console
|
|||||||
"terminal does not support ANSI escape sequences.");
|
"terminal does not support ANSI escape sequences.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return console.RunExclusive(() =>
|
||||||
|
{
|
||||||
var converter = Converter ?? TypeConverterHelper.ConvertToString;
|
var converter = Converter ?? TypeConverterHelper.ConvertToString;
|
||||||
var list = new RenderableMultiSelectionList<T>(
|
var list = new RenderableMultiSelectionList<T>(
|
||||||
console, Title, PageSize, Choices,
|
console, Title, PageSize, Choices,
|
||||||
@ -130,6 +137,7 @@ namespace Spectre.Console
|
|||||||
return list.Selections
|
return list.Selections
|
||||||
.Select(index => Choices[index])
|
.Select(index => Choices[index])
|
||||||
.ToList();
|
.ToList();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -68,6 +68,8 @@ namespace Spectre.Console
|
|||||||
"terminal does not support ANSI escape sequences.");
|
"terminal does not support ANSI escape sequences.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return console.RunExclusive(() =>
|
||||||
|
{
|
||||||
var converter = Converter ?? TypeConverterHelper.ConvertToString;
|
var converter = Converter ?? TypeConverterHelper.ConvertToString;
|
||||||
var list = new RenderableSelectionList<T>(
|
var list = new RenderableSelectionList<T>(
|
||||||
console, Title, PageSize, Choices,
|
console, Title, PageSize, Choices,
|
||||||
@ -97,6 +99,7 @@ namespace Spectre.Console
|
|||||||
console.Cursor.Show();
|
console.Cursor.Show();
|
||||||
|
|
||||||
return Choices[list.Index];
|
return Choices[list.Index];
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -100,6 +100,8 @@ namespace Spectre.Console
|
|||||||
throw new ArgumentNullException(nameof(console));
|
throw new ArgumentNullException(nameof(console));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return console.RunExclusive(() =>
|
||||||
|
{
|
||||||
var promptStyle = PromptStyle ?? Style.Plain;
|
var promptStyle = PromptStyle ?? Style.Plain;
|
||||||
var converter = Converter ?? TypeConverterHelper.ConvertToString;
|
var converter = Converter ?? TypeConverterHelper.ConvertToString;
|
||||||
var choices = Choices.Select(choice => converter(choice)).ToList();
|
var choices = Choices.Select(choice => converter(choice)).ToList();
|
||||||
@ -160,6 +162,7 @@ namespace Spectre.Console
|
|||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user