From cba299eee30a9a275cdb32f5d9ed2cabd3ea3b6f Mon Sep 17 00:00:00 2001 From: Tom Deseyn Date: Thu, 9 Mar 2023 10:26:42 +0100 Subject: [PATCH 1/3] [I]AnsiConsole: add async overloads for Prompt/Ask/Confirm. --- src/Spectre.Console/AnsiConsole.Prompt.cs | 62 +++++++++++++++++ .../AnsiConsoleExtensions.Prompt.cs | 66 +++++++++++++++++++ 2 files changed, 128 insertions(+) diff --git a/src/Spectre.Console/AnsiConsole.Prompt.cs b/src/Spectre.Console/AnsiConsole.Prompt.cs index ef892ae9e..5e88efaa0 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; /// @@ -60,4 +62,64 @@ public static bool Confirm(string prompt, bool defaultValue = true) } .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. + /// + /// 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. + /// + /// 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. + /// + /// 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 From ca5deb3d678cbeb70ac576d6cd2ed7faffcbac01 Mon Sep 17 00:00:00 2001 From: Frank Ray <52075808+FrankRay78@users.noreply.github.com> Date: Fri, 22 Nov 2024 11:48:56 +0000 Subject: [PATCH 2/3] Added unit test coverage - AskAsync, ConfirmAsync --- .../Unit/AnsiConsoleTests.Prompt.cs | 52 +++++++++++++++---- 1 file changed, 41 insertions(+), 11 deletions(-) diff --git a/test/Spectre.Console.Tests/Unit/AnsiConsoleTests.Prompt.cs b/test/Spectre.Console.Tests/Unit/AnsiConsoleTests.Prompt.cs index e6fa30c5d..dc512b436 100644 --- a/test/Spectre.Console.Tests/Unit/AnsiConsoleTests.Prompt.cs +++ b/test/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)); From d9c99e22d05156707b8c542553f7be1959fa8c9f Mon Sep 17 00:00:00 2001 From: Frank Ray <52075808+FrankRay78@users.noreply.github.com> Date: Fri, 22 Nov 2024 11:58:46 +0000 Subject: [PATCH 3/3] Reordered methods to group non-async/async of the same tests together --- src/Spectre.Console/AnsiConsole.Prompt.cs | 72 +++++++++++------------ 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/src/Spectre.Console/AnsiConsole.Prompt.cs b/src/Spectre.Console/AnsiConsole.Prompt.cs index 5e88efaa0..11657d0a7 100644 --- a/src/Spectre.Console/AnsiConsole.Prompt.cs +++ b/src/Spectre.Console/AnsiConsole.Prompt.cs @@ -27,69 +27,54 @@ public static T Prompt(IPrompt prompt) /// Displays a prompt to the user. /// /// The prompt result type. - /// The prompt markup text. + /// The prompt to display. + /// The token to monitor for cancellation requests. /// The prompt input result. - public static T Ask(string prompt) + public static Task PromptAsync(IPrompt prompt, CancellationToken cancellationToken = default) { - return new TextPrompt(prompt).Show(Console); + if (prompt is null) + { + throw new ArgumentNullException(nameof(prompt)); + } + + return prompt.ShowAsync(Console, cancellationToken); } /// - /// Displays a prompt to the user with a given default. + /// Displays a prompt to the user. /// /// The prompt result type. /// The prompt markup text. - /// The default value. /// The prompt input result. - public static T Ask(string prompt, T defaultValue) - { - return new TextPrompt(prompt) - .DefaultValue(defaultValue) - .Show(Console); - } - - /// - /// Displays a prompt with two choices, yes or no. - /// - /// The prompt markup text. - /// Specifies the default answer. - /// true if the user selected "yes", otherwise false. - public static bool Confirm(string prompt, bool defaultValue = true) + public static T Ask(string prompt) { - return new ConfirmationPrompt(prompt) - { - DefaultValue = defaultValue, - } - .Show(Console); + return new TextPrompt(prompt).Show(Console); } /// /// Displays a prompt to the user. /// /// The prompt result type. - /// The prompt to display. + /// The prompt markup text. /// The token to monitor for cancellation requests. /// The prompt input result. - public static Task PromptAsync(IPrompt prompt, CancellationToken cancellationToken = default) + public static Task AskAsync(string prompt, CancellationToken cancellationToken = default) { - if (prompt is null) - { - throw new ArgumentNullException(nameof(prompt)); - } - - return prompt.ShowAsync(Console, cancellationToken); + return new TextPrompt(prompt).ShowAsync(Console, cancellationToken); } /// - /// Displays a prompt to the user. + /// Displays a prompt to the user with a given default. /// /// The prompt result type. /// The prompt markup text. - /// The token to monitor for cancellation requests. + /// The default value. /// The prompt input result. - public static Task AskAsync(string prompt, CancellationToken cancellationToken = default) + public static T Ask(string prompt, T defaultValue) { - return new TextPrompt(prompt).ShowAsync(Console, cancellationToken); + return new TextPrompt(prompt) + .DefaultValue(defaultValue) + .Show(Console); } /// @@ -107,6 +92,21 @@ public static Task AskAsync(string prompt, T defaultValue, CancellationTok .ShowAsync(Console, cancellationToken); } + /// + /// Displays a prompt with two choices, yes or no. + /// + /// The prompt markup text. + /// Specifies the default answer. + /// true if the user selected "yes", otherwise false. + public static bool Confirm(string prompt, bool defaultValue = true) + { + return new ConfirmationPrompt(prompt) + { + DefaultValue = defaultValue, + } + .Show(Console); + } + /// /// Displays a prompt with two choices, yes or no. ///