Add culture option to TypeConverterHelper, TextPrompt and AnsiConsole (#1014)

* Add culture option to TypeConverterHelper, TextPrompt and AnsiConsole

* Add IHasCulture interface
This commit is contained in:
Łukasz Sowa 2022-10-15 11:19:06 +02:00 committed by GitHub
parent 5f1121e8e1
commit 6a4d8c8f30
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 82 additions and 9 deletions

View File

@ -34,6 +34,21 @@ public static partial class AnsiConsoleExtensions
return new TextPrompt<T>(prompt).Show(console);
}
/// <summary>
/// Displays a prompt to the user.
/// </summary>
/// <typeparam name="T">The prompt result type.</typeparam>
/// <param name="console">The console.</param>
/// <param name="prompt">The prompt markup text.</param>
/// <param name="culture">Specific CultureInfo to use when converting input.</param>
/// <returns>The prompt input result.</returns>
public static T Ask<T>(this IAnsiConsole console, string prompt, CultureInfo? culture)
{
var textPrompt = new TextPrompt<T>(prompt);
textPrompt.Culture = culture;
return textPrompt.Show(console);
}
/// <summary>
/// Displays a prompt with two choices, yes or no.
/// </summary>

View File

@ -21,6 +21,28 @@ internal static class TypeConverterHelper
}
}
public static bool TryConvertFromStringWithCulture<T>(string input, CultureInfo? info, [MaybeNull] out T result)
{
try
{
if (info == null)
{
return TryConvertFromString<T>(input, out result);
}
else
{
result = (T)GetTypeConverter<T>().ConvertFromString(null!, info, input);
}
return true;
}
catch
{
result = default;
return false;
}
}
public static TypeConverter GetTypeConverter<T>()
{
var converter = TypeDescriptor.GetConverter(typeof(T));

View File

@ -4,7 +4,7 @@ namespace Spectre.Console;
/// Represents a prompt.
/// </summary>
/// <typeparam name="T">The prompt result type.</typeparam>
public sealed class TextPrompt<T> : IPrompt<T>
public sealed class TextPrompt<T> : IPrompt<T>, IHasCulture
{
private readonly string _prompt;
private readonly StringComparer? _comparer;
@ -19,6 +19,11 @@ public sealed class TextPrompt<T> : IPrompt<T>
/// </summary>
public List<T> Choices { get; } = new List<T>();
/// <summary>
/// Gets or sets the culture to use when converting input to object.
/// </summary>
public CultureInfo? Culture { get; set; }
/// <summary>
/// Gets or sets the message for invalid choices.
/// </summary>
@ -28,12 +33,12 @@ public sealed class TextPrompt<T> : IPrompt<T>
/// Gets or sets a value indicating whether input should
/// be hidden in the console.
/// </summary>
public bool IsSecret { get; set; }
public bool IsSecret { get; set; }
/// <summary>
/// Gets or sets the character to use while masking
/// Gets or sets the character to use while masking
/// a secret prompt.
/// </summary>
/// </summary>
public char? Mask { get; set; } = '*';
/// <summary>
@ -131,7 +136,7 @@ public sealed class TextPrompt<T> : IPrompt<T>
if (string.IsNullOrWhiteSpace(input))
{
if (DefaultValue != null)
{
{
var defaultValue = converter(DefaultValue.Value);
console.Write(IsSecret ? defaultValue.Mask(Mask) : defaultValue, promptStyle);
console.WriteLine();
@ -160,7 +165,7 @@ public sealed class TextPrompt<T> : IPrompt<T>
continue;
}
}
else if (!TypeConverterHelper.TryConvertFromString<T>(input, out result) || result == null)
else if (!TypeConverterHelper.TryConvertFromStringWithCulture<T>(input, Culture, out result) || result == null)
{
console.MarkupLine(ValidationErrorMessage);
WritePrompt(console);
@ -208,8 +213,8 @@ public sealed class TextPrompt<T> : IPrompt<T>
{
appendSuffix = true;
var converter = Converter ?? TypeConverterHelper.ConvertToString;
var defaultValueStyle = DefaultValueStyle?.ToMarkup() ?? "green";
var defaultValue = converter(DefaultValue.Value);
var defaultValueStyle = DefaultValueStyle?.ToMarkup() ?? "green";
var defaultValue = converter(DefaultValue.Value);
builder.AppendFormat(
CultureInfo.InvariantCulture,

View File

@ -20,4 +20,35 @@ public partial class AnsiConsoleTests
result.ShouldBe(expected);
}
}
public sealed class Ask
{
[Fact]
public void Should_Return_Correct_DateTime_When_Asked_PL_Culture()
{
// Given
var console = new TestConsole().EmitAnsiSequences();
console.Input.PushTextWithEnter("1/2/1998");
// When
var dateTime = console.Ask<DateTime>(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()
{
// Given
var console = new TestConsole().EmitAnsiSequences();
console.Input.PushTextWithEnter("2/1/1998");
// When
var dateTime = console.Ask<DateTime>(string.Empty, CultureInfo.GetCultureInfo("en-US"));
// Then
dateTime.ShouldBe(new DateTime(1998, 2, 1));
}
}
}