mirror of
https://github.com/nsnail/spectre.console.git
synced 2025-04-14 16:02:50 +08:00
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:
parent
5f1121e8e1
commit
6a4d8c8f30
@ -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>
|
||||
|
@ -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));
|
||||
|
@ -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,
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user