mirror of
https://github.com/nsnail/spectre.console.git
synced 2025-04-16 17:02:51 +08:00
parent
e280b82679
commit
1cf30f62fc
@ -0,0 +1 @@
|
|||||||
|
Favorite fruit? [Banana/Bandana/Orange]: Band Bandana
|
@ -0,0 +1 @@
|
|||||||
|
Favorite fruit? [Banana/Orange] (Banana): Banana
|
@ -0,0 +1 @@
|
|||||||
|
Favorite fruit? [Apple/Banana/Orange]: Apple Banana
|
@ -23,7 +23,11 @@ namespace Spectre.Console.Tests
|
|||||||
{
|
{
|
||||||
PushCharacter(character);
|
PushCharacter(character);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PushTextWithEnter(string input)
|
||||||
|
{
|
||||||
|
PushText(input);
|
||||||
PushKey(ConsoleKey.Enter);
|
PushKey(ConsoleKey.Enter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Shouldly;
|
|
||||||
using Spectre.Console.Rendering;
|
using Spectre.Console.Rendering;
|
||||||
using VerifyXunit;
|
using VerifyXunit;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
@ -13,8 +13,8 @@ namespace Spectre.Console.Tests.Unit
|
|||||||
{
|
{
|
||||||
// Given
|
// Given
|
||||||
var console = new PlainConsole();
|
var console = new PlainConsole();
|
||||||
console.Input.PushText("ninety-nine");
|
console.Input.PushTextWithEnter("ninety-nine");
|
||||||
console.Input.PushText("99");
|
console.Input.PushTextWithEnter("99");
|
||||||
|
|
||||||
// When
|
// When
|
||||||
console.Prompt(new TextPrompt<int>("Age?"));
|
console.Prompt(new TextPrompt<int>("Age?"));
|
||||||
@ -46,8 +46,8 @@ namespace Spectre.Console.Tests.Unit
|
|||||||
{
|
{
|
||||||
// Given
|
// Given
|
||||||
var console = new PlainConsole();
|
var console = new PlainConsole();
|
||||||
console.Input.PushText("Apple");
|
console.Input.PushTextWithEnter("Apple");
|
||||||
console.Input.PushText("Banana");
|
console.Input.PushTextWithEnter("Banana");
|
||||||
|
|
||||||
// When
|
// When
|
||||||
console.Prompt(
|
console.Prompt(
|
||||||
@ -65,7 +65,7 @@ namespace Spectre.Console.Tests.Unit
|
|||||||
{
|
{
|
||||||
// Given
|
// Given
|
||||||
var console = new PlainConsole();
|
var console = new PlainConsole();
|
||||||
console.Input.PushText("Orange");
|
console.Input.PushTextWithEnter("Orange");
|
||||||
|
|
||||||
// When
|
// When
|
||||||
console.Prompt(
|
console.Prompt(
|
||||||
@ -78,15 +78,74 @@ namespace Spectre.Console.Tests.Unit
|
|||||||
return Verifier.Verify(console.Output);
|
return Verifier.Verify(console.Output);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public Task Should_Auto_Complete_To_First_Choice_If_Pressing_Tab_On_Empty_String()
|
||||||
|
{
|
||||||
|
// Given
|
||||||
|
var console = new PlainConsole();
|
||||||
|
console.Input.PushKey(ConsoleKey.Tab);
|
||||||
|
console.Input.PushKey(ConsoleKey.Enter);
|
||||||
|
|
||||||
|
// When
|
||||||
|
console.Prompt(
|
||||||
|
new TextPrompt<string>("Favorite fruit?")
|
||||||
|
.AddChoice("Banana")
|
||||||
|
.AddChoice("Orange")
|
||||||
|
.DefaultValue("Banana"));
|
||||||
|
|
||||||
|
// Then
|
||||||
|
return Verifier.Verify(console.Output);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public Task Should_Auto_Complete_To_Best_Match()
|
||||||
|
{
|
||||||
|
// Given
|
||||||
|
var console = new PlainConsole();
|
||||||
|
console.Input.PushText("Band");
|
||||||
|
console.Input.PushKey(ConsoleKey.Tab);
|
||||||
|
console.Input.PushKey(ConsoleKey.Enter);
|
||||||
|
|
||||||
|
// When
|
||||||
|
console.Prompt(
|
||||||
|
new TextPrompt<string>("Favorite fruit?")
|
||||||
|
.AddChoice("Banana")
|
||||||
|
.AddChoice("Bandana")
|
||||||
|
.AddChoice("Orange"));
|
||||||
|
|
||||||
|
// Then
|
||||||
|
return Verifier.Verify(console.Output);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public Task Should_Auto_Complete_To_Next_Choice_When_Pressing_Tab_On_A_Match()
|
||||||
|
{
|
||||||
|
// Given
|
||||||
|
var console = new PlainConsole();
|
||||||
|
console.Input.PushText("Apple");
|
||||||
|
console.Input.PushKey(ConsoleKey.Tab);
|
||||||
|
console.Input.PushKey(ConsoleKey.Enter);
|
||||||
|
|
||||||
|
// When
|
||||||
|
console.Prompt(
|
||||||
|
new TextPrompt<string>("Favorite fruit?")
|
||||||
|
.AddChoice("Apple")
|
||||||
|
.AddChoice("Banana")
|
||||||
|
.AddChoice("Orange"));
|
||||||
|
|
||||||
|
// Then
|
||||||
|
return Verifier.Verify(console.Output);
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public Task Should_Return_Error_If_Custom_Validation_Fails()
|
public Task Should_Return_Error_If_Custom_Validation_Fails()
|
||||||
{
|
{
|
||||||
// Given
|
// Given
|
||||||
var console = new PlainConsole();
|
var console = new PlainConsole();
|
||||||
console.Input.PushText("22");
|
console.Input.PushTextWithEnter("22");
|
||||||
console.Input.PushText("102");
|
console.Input.PushTextWithEnter("102");
|
||||||
console.Input.PushText("ABC");
|
console.Input.PushTextWithEnter("ABC");
|
||||||
console.Input.PushText("99");
|
console.Input.PushTextWithEnter("99");
|
||||||
|
|
||||||
// When
|
// When
|
||||||
console.Prompt(
|
console.Prompt(
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace Spectre.Console
|
namespace Spectre.Console
|
||||||
{
|
{
|
||||||
@ -7,7 +10,7 @@ namespace Spectre.Console
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static partial class AnsiConsoleExtensions
|
public static partial class AnsiConsoleExtensions
|
||||||
{
|
{
|
||||||
internal static string ReadLine(this IAnsiConsole console, Style? style, bool secret)
|
internal static string ReadLine(this IAnsiConsole console, Style? style, bool secret, IEnumerable<string>? items = null)
|
||||||
{
|
{
|
||||||
if (console is null)
|
if (console is null)
|
||||||
{
|
{
|
||||||
@ -15,35 +18,83 @@ namespace Spectre.Console
|
|||||||
}
|
}
|
||||||
|
|
||||||
style ??= Style.Plain;
|
style ??= Style.Plain;
|
||||||
|
var text = string.Empty;
|
||||||
|
|
||||||
|
var autocomplete = new List<string>(items ?? Enumerable.Empty<string>());
|
||||||
|
|
||||||
var result = string.Empty;
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
var key = console.Input.ReadKey(true);
|
var key = console.Input.ReadKey(true);
|
||||||
|
|
||||||
if (key.Key == ConsoleKey.Enter)
|
if (key.Key == ConsoleKey.Enter)
|
||||||
{
|
{
|
||||||
return result;
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key.Key == ConsoleKey.Tab && autocomplete.Count > 0)
|
||||||
|
{
|
||||||
|
var replace = AutoComplete(autocomplete, text);
|
||||||
|
if (!string.IsNullOrEmpty(replace))
|
||||||
|
{
|
||||||
|
// Render the suggestion
|
||||||
|
console.Write("\b \b".Repeat(text.Length), style);
|
||||||
|
console.Write(replace);
|
||||||
|
text = replace;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (key.Key == ConsoleKey.Backspace)
|
if (key.Key == ConsoleKey.Backspace)
|
||||||
{
|
{
|
||||||
if (result.Length > 0)
|
if (text.Length > 0)
|
||||||
{
|
{
|
||||||
result = result.Substring(0, result.Length - 1);
|
text = text.Substring(0, text.Length - 1);
|
||||||
console.Write("\b \b");
|
console.Write("\b \b");
|
||||||
}
|
}
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
result += key.KeyChar.ToString();
|
|
||||||
|
|
||||||
if (!char.IsControl(key.KeyChar))
|
if (!char.IsControl(key.KeyChar))
|
||||||
{
|
{
|
||||||
|
text += key.KeyChar.ToString();
|
||||||
console.Write(secret ? "*" : key.KeyChar.ToString(), style);
|
console.Write(secret ? "*" : key.KeyChar.ToString(), style);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static string AutoComplete(List<string> autocomplete, string text)
|
||||||
|
{
|
||||||
|
var found = autocomplete.Find(i => i == text);
|
||||||
|
var replace = string.Empty;
|
||||||
|
|
||||||
|
if (found == null)
|
||||||
|
{
|
||||||
|
// Get the closest match
|
||||||
|
var next = autocomplete.Find(i => i.StartsWith(text, true, CultureInfo.InvariantCulture));
|
||||||
|
if (next != null)
|
||||||
|
{
|
||||||
|
replace = next;
|
||||||
|
}
|
||||||
|
else if (string.IsNullOrEmpty(text))
|
||||||
|
{
|
||||||
|
// Use the first item
|
||||||
|
replace = autocomplete[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Get the next match
|
||||||
|
var index = autocomplete.IndexOf(found) + 1;
|
||||||
|
if (index >= autocomplete.Count)
|
||||||
|
{
|
||||||
|
index = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
replace = autocomplete[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
return replace;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
55
src/Spectre.Console/Internal/TypeConverterHelper.cs
Normal file
55
src/Spectre.Console/Internal/TypeConverterHelper.cs
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
using System;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
|
namespace Spectre.Console.Internal
|
||||||
|
{
|
||||||
|
internal static class TypeConverterHelper
|
||||||
|
{
|
||||||
|
public static string ConvertToString<T>(T input)
|
||||||
|
{
|
||||||
|
return GetTypeConverter<T>().ConvertToInvariantString(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
[SuppressMessage("Design", "CA1031:Do not catch general exception types")]
|
||||||
|
public static bool TryConvertFromString<T>(string input, [MaybeNull] out T result)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
result = (T)GetTypeConverter<T>().ConvertFromInvariantString(input);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
result = default;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TypeConverter GetTypeConverter<T>()
|
||||||
|
{
|
||||||
|
var converter = TypeDescriptor.GetConverter(typeof(T));
|
||||||
|
if (converter != null)
|
||||||
|
{
|
||||||
|
return converter;
|
||||||
|
}
|
||||||
|
|
||||||
|
var attribute = typeof(T).GetCustomAttribute<TypeConverterAttribute>();
|
||||||
|
if (attribute != null)
|
||||||
|
{
|
||||||
|
var type = Type.GetType(attribute.ConverterTypeName, false, false);
|
||||||
|
if (type != null)
|
||||||
|
{
|
||||||
|
converter = Activator.CreateInstance(type) as TypeConverter;
|
||||||
|
if (converter != null)
|
||||||
|
{
|
||||||
|
return converter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new InvalidOperationException("Could not find type converter");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -2,16 +2,17 @@
|
|||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFrameworks>net5.0;netstandard2.0</TargetFrameworks>
|
<TargetFrameworks>net5.0;netstandard2.0</TargetFrameworks>
|
||||||
|
<LangVersion>9.0</LangVersion>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Remove="Figlet\Fonts\Standard.flf" />
|
<None Remove="Widgets\Figlet\Fonts\Standard.flf" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<AdditionalFiles Include="..\stylecop.json" Link="Properties/stylecop.json" />
|
<AdditionalFiles Include="..\stylecop.json" Link="Properties/stylecop.json" />
|
||||||
<EmbeddedResource Include="Figlet\Fonts\Standard.flf" />
|
<EmbeddedResource Include="Widgets\Figlet\Fonts\Standard.flf" />
|
||||||
<None Include="../../resources/gfx/small-logo.png" Pack="true" PackagePath="\" Link="Properties/small-logo.png" />
|
<None Include="../../resources/gfx/small-logo.png" Pack="true" PackagePath="\" Link="Properties/small-logo.png" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
@ -10,6 +10,8 @@ namespace Spectre.Console
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class FigletFont
|
public sealed class FigletFont
|
||||||
{
|
{
|
||||||
|
private const string StandardFont = "Spectre.Console/Widgets/Figlet/Fonts/Standard.flf";
|
||||||
|
|
||||||
private readonly Dictionary<int, FigletCharacter> _characters;
|
private readonly Dictionary<int, FigletCharacter> _characters;
|
||||||
private static readonly Lazy<FigletFont> _standard;
|
private static readonly Lazy<FigletFont> _standard;
|
||||||
|
|
||||||
@ -40,7 +42,8 @@ namespace Spectre.Console
|
|||||||
|
|
||||||
static FigletFont()
|
static FigletFont()
|
||||||
{
|
{
|
||||||
_standard = new Lazy<FigletFont>(() => Parse(ResourceReader.ReadManifestData("Spectre.Console/Figlet/Fonts/Standard.flf")));
|
_standard = new Lazy<FigletFont>(() => Parse(
|
||||||
|
ResourceReader.ReadManifestData(StandardFont)));
|
||||||
}
|
}
|
||||||
|
|
||||||
internal FigletFont(IEnumerable<FigletCharacter> characters, FigletHeader header)
|
internal FigletFont(IEnumerable<FigletCharacter> characters, FigletHeader header)
|
12
src/Spectre.Console/Widgets/Prompt/DefaultPromptValue.cs
Normal file
12
src/Spectre.Console/Widgets/Prompt/DefaultPromptValue.cs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
namespace Spectre.Console
|
||||||
|
{
|
||||||
|
internal sealed class DefaultPromptValue<T>
|
||||||
|
{
|
||||||
|
public T Value { get; }
|
||||||
|
|
||||||
|
public DefaultPromptValue(T value)
|
||||||
|
{
|
||||||
|
Value = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,11 +1,10 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.ComponentModel;
|
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using Spectre.Console.Internal;
|
||||||
|
|
||||||
namespace Spectre.Console
|
namespace Spectre.Console
|
||||||
{
|
{
|
||||||
@ -68,27 +67,7 @@ namespace Spectre.Console
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the default value.
|
/// Gets or sets the default value.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal DefaultValueContainer? DefaultValue { get; set; }
|
internal DefaultPromptValue<T>? DefaultValue { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// A nullable container for a default value.
|
|
||||||
/// </summary>
|
|
||||||
internal sealed class DefaultValueContainer
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the default value.
|
|
||||||
/// </summary>
|
|
||||||
public T Value { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="DefaultValueContainer"/> class.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="value">The default value.</param>
|
|
||||||
public DefaultValueContainer(T value)
|
|
||||||
{
|
|
||||||
Value = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="TextPrompt{T}"/> class.
|
/// Initializes a new instance of the <see cref="TextPrompt{T}"/> class.
|
||||||
@ -116,19 +95,20 @@ namespace Spectre.Console
|
|||||||
}
|
}
|
||||||
|
|
||||||
var promptStyle = PromptStyle ?? Style.Plain;
|
var promptStyle = PromptStyle ?? Style.Plain;
|
||||||
|
var choices = Choices.Select(choice => TypeConverterHelper.ConvertToString(choice));
|
||||||
|
|
||||||
WritePrompt(console);
|
WritePrompt(console);
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
var input = console.ReadLine(promptStyle, IsSecret);
|
var input = console.ReadLine(promptStyle, IsSecret, choices);
|
||||||
|
|
||||||
// Nothing entered?
|
// Nothing entered?
|
||||||
if (string.IsNullOrWhiteSpace(input))
|
if (string.IsNullOrWhiteSpace(input))
|
||||||
{
|
{
|
||||||
if (DefaultValue != null)
|
if (DefaultValue != null)
|
||||||
{
|
{
|
||||||
console.Write(TextPrompt<T>.GetTypeConverter().ConvertToInvariantString(DefaultValue.Value), promptStyle);
|
console.Write(TypeConverterHelper.ConvertToString(DefaultValue.Value), promptStyle);
|
||||||
console.WriteLine();
|
console.WriteLine();
|
||||||
return DefaultValue.Value;
|
return DefaultValue.Value;
|
||||||
}
|
}
|
||||||
@ -142,7 +122,7 @@ namespace Spectre.Console
|
|||||||
console.WriteLine();
|
console.WriteLine();
|
||||||
|
|
||||||
// Try convert the value to the expected type.
|
// Try convert the value to the expected type.
|
||||||
if (!TextPrompt<T>.TryConvert(input, out var result) || result == null)
|
if (!TypeConverterHelper.TryConvertFromString<T>(input, out var result) || result == null)
|
||||||
{
|
{
|
||||||
console.MarkupLine(ValidationErrorMessage);
|
console.MarkupLine(ValidationErrorMessage);
|
||||||
WritePrompt(console);
|
WritePrompt(console);
|
||||||
@ -191,7 +171,7 @@ namespace Spectre.Console
|
|||||||
|
|
||||||
if (ShowChoices && Choices.Count > 0)
|
if (ShowChoices && Choices.Count > 0)
|
||||||
{
|
{
|
||||||
var choices = string.Join("/", Choices.Select(choice => TextPrompt<T>.GetTypeConverter().ConvertToInvariantString(choice)));
|
var choices = string.Join("/", Choices.Select(choice => TypeConverterHelper.ConvertToString(choice)));
|
||||||
builder.AppendFormat(CultureInfo.InvariantCulture, " [blue][[{0}]][/]", choices);
|
builder.AppendFormat(CultureInfo.InvariantCulture, " [blue][[{0}]][/]", choices);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -200,7 +180,7 @@ namespace Spectre.Console
|
|||||||
builder.AppendFormat(
|
builder.AppendFormat(
|
||||||
CultureInfo.InvariantCulture,
|
CultureInfo.InvariantCulture,
|
||||||
" [green]({0})[/]",
|
" [green]({0})[/]",
|
||||||
TextPrompt<T>.GetTypeConverter().ConvertToInvariantString(DefaultValue.Value));
|
TypeConverterHelper.ConvertToString(DefaultValue.Value));
|
||||||
}
|
}
|
||||||
|
|
||||||
var markup = builder.ToString().Trim();
|
var markup = builder.ToString().Trim();
|
||||||
@ -213,58 +193,6 @@ namespace Spectre.Console
|
|||||||
console.Markup(markup + " ");
|
console.Markup(markup + " ");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Tries to convert the input string to <typeparamref name="T"/>.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="input">The input to convert.</param>
|
|
||||||
/// <param name="result">The result.</param>
|
|
||||||
/// <returns><c>true</c> if the conversion succeeded, otherwise <c>false</c>.</returns>
|
|
||||||
[SuppressMessage("Design", "CA1031:Do not catch general exception types")]
|
|
||||||
private static bool TryConvert(string input, [MaybeNull] out T result)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
result = (T)TextPrompt<T>.GetTypeConverter().ConvertFromInvariantString(input);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
#pragma warning disable CS8601 // Possible null reference assignment.
|
|
||||||
result = default;
|
|
||||||
#pragma warning restore CS8601 // Possible null reference assignment.
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the type converter that's used to convert values.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>The type converter that's used to convert values.</returns>
|
|
||||||
private static TypeConverter GetTypeConverter()
|
|
||||||
{
|
|
||||||
var converter = TypeDescriptor.GetConverter(typeof(T));
|
|
||||||
if (converter != null)
|
|
||||||
{
|
|
||||||
return converter;
|
|
||||||
}
|
|
||||||
|
|
||||||
var attribute = typeof(T).GetCustomAttribute<TypeConverterAttribute>();
|
|
||||||
if (attribute != null)
|
|
||||||
{
|
|
||||||
var type = Type.GetType(attribute.ConverterTypeName, false, false);
|
|
||||||
if (type != null)
|
|
||||||
{
|
|
||||||
converter = Activator.CreateInstance(type) as TypeConverter;
|
|
||||||
if (converter != null)
|
|
||||||
{
|
|
||||||
return converter;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new InvalidOperationException("Could not find type converter");
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool ValidateResult(T value, [NotNullWhen(false)] out string? message)
|
private bool ValidateResult(T value, [NotNullWhen(false)] out string? message)
|
||||||
{
|
{
|
||||||
if (Validator != null)
|
if (Validator != null)
|
@ -177,7 +177,7 @@ namespace Spectre.Console
|
|||||||
throw new ArgumentNullException(nameof(obj));
|
throw new ArgumentNullException(nameof(obj));
|
||||||
}
|
}
|
||||||
|
|
||||||
obj.DefaultValue = new TextPrompt<T>.DefaultValueContainer(value);
|
obj.DefaultValue = new DefaultPromptValue<T>(value);
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
@ -1,7 +1,7 @@
|
|||||||
namespace Spectre.Console
|
namespace Spectre.Console
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a validation result.
|
/// Represents a prompt validation result.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class ValidationResult
|
public sealed class ValidationResult
|
||||||
{
|
{
|
Loading…
x
Reference in New Issue
Block a user