diff --git a/src/Spectre.Console/AnsiConsole.Prompt.cs b/src/Spectre.Console/AnsiConsole.Prompt.cs index ef892ae9e..11657d0a7 100644 --- a/src/Spectre.Console/AnsiConsole.Prompt.cs +++ b/src/Spectre.Console/AnsiConsole.Prompt.cs @@ -1,3 +1,5 @@ +using System.Threading.Tasks; + namespace Spectre.Console; /// @@ -21,6 +23,23 @@ public static T Prompt(IPrompt prompt) return prompt.Show(Console); } + /// + /// Displays a prompt to the user. + /// + /// The prompt result type. + /// The prompt to display. + /// The token to monitor for cancellation requests. + /// The prompt input result. + public static Task PromptAsync(IPrompt prompt, CancellationToken cancellationToken = default) + { + if (prompt is null) + { + throw new ArgumentNullException(nameof(prompt)); + } + + return prompt.ShowAsync(Console, cancellationToken); + } + /// /// Displays a prompt to the user. /// @@ -32,6 +51,18 @@ public static T Ask(string prompt) return new TextPrompt(prompt).Show(Console); } + /// + /// Displays a prompt to the user. + /// + /// The prompt result type. + /// The prompt markup text. + /// The token to monitor for cancellation requests. + /// The prompt input result. + public static Task AskAsync(string prompt, CancellationToken cancellationToken = default) + { + return new TextPrompt(prompt).ShowAsync(Console, cancellationToken); + } + /// /// Displays a prompt to the user with a given default. /// @@ -46,6 +77,21 @@ public static T Ask(string prompt, T defaultValue) .Show(Console); } + /// + /// Displays a prompt to the user with a given default. + /// + /// The prompt result type. + /// The prompt markup text. + /// The default value. + /// The token to monitor for cancellation requests. + /// The prompt input result. + public static Task AskAsync(string prompt, T defaultValue, CancellationToken cancellationToken = default) + { + return new TextPrompt(prompt) + .DefaultValue(defaultValue) + .ShowAsync(Console, cancellationToken); + } + /// /// Displays a prompt with two choices, yes or no. /// @@ -60,4 +106,20 @@ public static bool Confirm(string prompt, bool defaultValue = true) } .Show(Console); } + + /// + /// Displays a prompt with two choices, yes or no. + /// + /// The prompt markup text. + /// Specifies the default answer. + /// The token to monitor for cancellation requests. + /// true if the user selected "yes", otherwise false. + public static Task ConfirmAsync(string prompt, bool defaultValue = true, CancellationToken cancellationToken = default) + { + return new ConfirmationPrompt(prompt) + { + DefaultValue = defaultValue, + } + .ShowAsync(Console, cancellationToken); + } } \ No newline at end of file diff --git a/src/Spectre.Console/Extensions/AnsiConsoleExtensions.Prompt.cs b/src/Spectre.Console/Extensions/AnsiConsoleExtensions.Prompt.cs index 382503f8b..450f35a98 100644 --- a/src/Spectre.Console/Extensions/AnsiConsoleExtensions.Prompt.cs +++ b/src/Spectre.Console/Extensions/AnsiConsoleExtensions.Prompt.cs @@ -1,3 +1,5 @@ +using System.Threading.Tasks; + namespace Spectre.Console; /// @@ -64,4 +66,68 @@ public static bool Confirm(this IAnsiConsole console, string prompt, bool defaul } .Show(console); } + + /// + /// Displays a prompt to the user. + /// + /// The prompt result type. + /// The console. + /// The prompt to display. + /// The token to monitor for cancellation requests. + /// The prompt input result. + public static Task PromptAsync(this IAnsiConsole console, IPrompt prompt, CancellationToken cancellationToken = default) + { + if (prompt is null) + { + throw new ArgumentNullException(nameof(prompt)); + } + + return prompt.ShowAsync(console, cancellationToken); + } + + /// + /// Displays a prompt to the user. + /// + /// The prompt result type. + /// The console. + /// The prompt markup text. + /// The token to monitor for cancellation requests. + /// The prompt input result. + public static Task AskAsync(this IAnsiConsole console, string prompt, CancellationToken cancellationToken = default) + { + return new TextPrompt(prompt).ShowAsync(console, cancellationToken); + } + + /// + /// Displays a prompt to the user. + /// + /// The prompt result type. + /// The console. + /// The prompt markup text. + /// Specific CultureInfo to use when converting input. + /// The token to monitor for cancellation requests. + /// The prompt input result. + public static Task AskAsync(this IAnsiConsole console, string prompt, CultureInfo? culture, CancellationToken cancellationToken = default) + { + var textPrompt = new TextPrompt(prompt); + textPrompt.Culture = culture; + return textPrompt.ShowAsync(console, cancellationToken); + } + + /// + /// Displays a prompt with two choices, yes or no. + /// + /// The console. + /// The prompt markup text. + /// Specifies the default answer. + /// The token to monitor for cancellation requests. + /// true if the user selected "yes", otherwise false. + public static Task ConfirmAsync(this IAnsiConsole console, string prompt, bool defaultValue = true, CancellationToken cancellationToken = default) + { + return new ConfirmationPrompt(prompt) + { + DefaultValue = defaultValue, + } + .ShowAsync(console, cancellationToken); + } } \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Tests/Unit/AnsiConsoleTests.Prompt.cs b/src/Tests/Spectre.Console.Tests/Unit/AnsiConsoleTests.Prompt.cs index e6fa30c5d..dc512b436 100644 --- a/src/Tests/Spectre.Console.Tests/Unit/AnsiConsoleTests.Prompt.cs +++ b/src/Tests/Spectre.Console.Tests/Unit/AnsiConsoleTests.Prompt.cs @@ -2,19 +2,29 @@ namespace Spectre.Console.Tests.Unit; public partial class AnsiConsoleTests { - public sealed class Prompt + public sealed class Confirm { [Theory] - [InlineData(true, true)] - [InlineData(false, false)] - public void Should_Return_Default_Value_If_Nothing_Is_Entered(bool expected, bool defaultValue) + [InlineData(true, true, true)] + [InlineData(false, true, true)] + [InlineData(true, false, false)] + [InlineData(false, false, false)] + public async Task Should_Return_Default_Value_If_Nothing_Is_Entered(bool async, bool defaultValue, bool expected) { // Given var console = new TestConsole().EmitAnsiSequences(); console.Input.PushKey(ConsoleKey.Enter); // When - var result = console.Confirm("Want some prompt?", defaultValue); + bool result; + if (async) + { + result = await console.ConfirmAsync("Want some prompt?", defaultValue); + } + else + { + result = console.Confirm("Want some prompt?", defaultValue); + } // Then result.ShouldBe(expected); @@ -23,29 +33,49 @@ public void Should_Return_Default_Value_If_Nothing_Is_Entered(bool expected, boo public sealed class Ask { - [Fact] - public void Should_Return_Correct_DateTime_When_Asked_PL_Culture() + [Theory] + [InlineData(true)] + [InlineData(false)] + public async Task Should_Return_Correct_DateTime_When_Asked_PL_Culture(bool async) { // Given var console = new TestConsole().EmitAnsiSequences(); console.Input.PushTextWithEnter("1/2/1998"); // When - var dateTime = console.Ask(string.Empty, CultureInfo.GetCultureInfo("pl-PL")); + DateTime dateTime; + if (async) + { + dateTime = await console.AskAsync(string.Empty, CultureInfo.GetCultureInfo("pl-PL")); + } + else + { + dateTime = console.Ask(string.Empty, CultureInfo.GetCultureInfo("pl-PL")); + } // Then dateTime.ShouldBe(new DateTime(1998, 2, 1)); } - [Fact] - public void Should_Return_Correct_DateTime_When_Asked_US_Culture() + [Theory] + [InlineData(true)] + [InlineData(false)] + public async Task Should_Return_Correct_DateTime_When_Asked_US_Culture(bool async) { // Given var console = new TestConsole().EmitAnsiSequences(); console.Input.PushTextWithEnter("2/1/1998"); // When - var dateTime = console.Ask(string.Empty, CultureInfo.GetCultureInfo("en-US")); + DateTime dateTime; + if (async) + { + dateTime = await console.AskAsync(string.Empty, CultureInfo.GetCultureInfo("en-US")); + } + else + { + dateTime = console.Ask(string.Empty, CultureInfo.GetCultureInfo("en-US")); + } // Then dateTime.ShouldBe(new DateTime(1998, 2, 1));