mirror of
https://github.com/nsnail/spectre.console.git
synced 2025-04-19 10:12:50 +08:00
Add support for arrays in [DefaultValue] attributes (#1164)
Fixes #1163
This commit is contained in:
parent
6acf9b8c63
commit
dac2097321
@ -65,6 +65,11 @@ internal sealed class CommandValueBinder
|
|||||||
|
|
||||||
private object GetArray(CommandParameter parameter, object? value)
|
private object GetArray(CommandParameter parameter, object? value)
|
||||||
{
|
{
|
||||||
|
if (value is Array)
|
||||||
|
{
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
// Add a new item to the array
|
// Add a new item to the array
|
||||||
var array = (Array?)_lookup.GetValue(parameter);
|
var array = (Array?)_lookup.GetValue(parameter);
|
||||||
Array newArray;
|
Array newArray;
|
||||||
|
@ -133,13 +133,33 @@ internal static class CommandValueResolver
|
|||||||
var (converter, _) = GetConverter(lookup, binder, resolver, parameter);
|
var (converter, _) = GetConverter(lookup, binder, resolver, parameter);
|
||||||
if (converter != null)
|
if (converter != null)
|
||||||
{
|
{
|
||||||
result = converter.ConvertFrom(result);
|
result = result is Array array ? ConvertArray(array, converter) : converter.ConvertFrom(result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Array ConvertArray(Array sourceArray, TypeConverter converter)
|
||||||
|
{
|
||||||
|
Array? targetArray = null;
|
||||||
|
for (var i = 0; i < sourceArray.Length; i++)
|
||||||
|
{
|
||||||
|
var item = sourceArray.GetValue(i);
|
||||||
|
if (item != null)
|
||||||
|
{
|
||||||
|
var converted = converter.ConvertFrom(item);
|
||||||
|
if (converted != null)
|
||||||
|
{
|
||||||
|
targetArray ??= Array.CreateInstance(converted.GetType(), sourceArray.Length);
|
||||||
|
targetArray.SetValue(converted, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return targetArray ?? sourceArray;
|
||||||
|
}
|
||||||
|
|
||||||
[SuppressMessage("Style", "IDE0019:Use pattern matching", Justification = "It's OK")]
|
[SuppressMessage("Style", "IDE0019:Use pattern matching", Justification = "It's OK")]
|
||||||
private static (TypeConverter? Converter, ConstructorInfo? StringConstructor) GetConverter(CommandValueLookup lookup, CommandValueBinder binder, ITypeResolver resolver, CommandParameter parameter)
|
private static (TypeConverter? Converter, ConstructorInfo? StringConstructor) GetConverter(CommandValueLookup lookup, CommandValueBinder binder, ITypeResolver resolver, CommandParameter parameter)
|
||||||
{
|
{
|
||||||
|
@ -348,7 +348,17 @@ internal static class HelpWriter
|
|||||||
var columns = new List<string> { GetOptionParts(option) };
|
var columns = new List<string> { GetOptionParts(option) };
|
||||||
if (defaultValueColumn)
|
if (defaultValueColumn)
|
||||||
{
|
{
|
||||||
columns.Add(option.DefaultValue == null ? " " : $"[bold]{option.DefaultValue.ToString().EscapeMarkup()}[/]");
|
static string Bold(object obj) => $"[bold]{obj.ToString().EscapeMarkup()}[/]";
|
||||||
|
|
||||||
|
var defaultValue = option.DefaultValue switch
|
||||||
|
{
|
||||||
|
null => " ",
|
||||||
|
"" => " ",
|
||||||
|
Array { Length: 0 } => " ",
|
||||||
|
Array array => string.Join(", ", array.Cast<object>().Select(Bold)),
|
||||||
|
_ => Bold(option.DefaultValue),
|
||||||
|
};
|
||||||
|
columns.Add(defaultValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
columns.Add(option.Description?.TrimEnd('.') ?? " ");
|
columns.Add(option.Description?.TrimEnd('.') ?? " ");
|
||||||
|
@ -9,4 +9,9 @@ public class LionSettings : CatSettings
|
|||||||
[CommandOption("-c <CHILDREN>")]
|
[CommandOption("-c <CHILDREN>")]
|
||||||
[Description("The number of children the lion has.")]
|
[Description("The number of children the lion has.")]
|
||||||
public int Children { get; set; }
|
public int Children { get; set; }
|
||||||
|
|
||||||
|
[CommandOption("-d <DAY>")]
|
||||||
|
[Description("The days the lion goes hunting.")]
|
||||||
|
[DefaultValue(new[] { DayOfWeek.Monday, DayOfWeek.Thursday })]
|
||||||
|
public DayOfWeek[] HuntDays { get; set; }
|
||||||
}
|
}
|
||||||
|
@ -33,3 +33,18 @@ public sealed class RequiredArgumentWithDefaultValueSettings : CommandSettings
|
|||||||
[DefaultValue("Hello World")]
|
[DefaultValue("Hello World")]
|
||||||
public string Greeting { get; set; }
|
public string Greeting { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public sealed class OptionWithArrayOfEnumDefaultValueSettings : CommandSettings
|
||||||
|
{
|
||||||
|
[CommandOption("--days")]
|
||||||
|
[DefaultValue(new[] { DayOfWeek.Sunday, DayOfWeek.Saturday })]
|
||||||
|
public DayOfWeek[] Days { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class OptionWithArrayOfStringDefaultValueAndTypeConverterSettings : CommandSettings
|
||||||
|
{
|
||||||
|
[CommandOption("--numbers")]
|
||||||
|
[DefaultValue(new[] { "2", "3" })]
|
||||||
|
[TypeConverter(typeof(StringToIntegerConverter))]
|
||||||
|
public int[] Numbers { get; set; }
|
||||||
|
}
|
||||||
|
@ -10,8 +10,9 @@ ARGUMENTS:
|
|||||||
|
|
||||||
OPTIONS:
|
OPTIONS:
|
||||||
DEFAULT
|
DEFAULT
|
||||||
-h, --help Prints help information
|
-h, --help Prints help information
|
||||||
-a, --alive Indicates whether or not the animal is alive
|
-a, --alive Indicates whether or not the animal is alive
|
||||||
-n, --name <VALUE>
|
-n, --name <VALUE>
|
||||||
--agility <VALUE> 10 The agility between 0 and 100
|
--agility <VALUE> 10 The agility between 0 and 100
|
||||||
-c <CHILDREN> The number of children the lion has
|
-c <CHILDREN> The number of children the lion has
|
||||||
|
-d <DAY> Monday, Thursday The days the lion goes hunting
|
@ -13,8 +13,9 @@ ARGUMENTS:
|
|||||||
|
|
||||||
OPTIONS:
|
OPTIONS:
|
||||||
DEFAULT
|
DEFAULT
|
||||||
-h, --help Prints help information
|
-h, --help Prints help information
|
||||||
-a, --alive Indicates whether or not the animal is alive
|
-a, --alive Indicates whether or not the animal is alive
|
||||||
-n, --name <VALUE>
|
-n, --name <VALUE>
|
||||||
--agility <VALUE> 10 The agility between 0 and 100
|
--agility <VALUE> 10 The agility between 0 and 100
|
||||||
-c <CHILDREN> The number of children the lion has
|
-c <CHILDREN> The number of children the lion has
|
||||||
|
-d <DAY> Monday, Thursday The days the lion goes hunting
|
@ -10,8 +10,9 @@ ARGUMENTS:
|
|||||||
|
|
||||||
OPTIONS:
|
OPTIONS:
|
||||||
DEFAULT
|
DEFAULT
|
||||||
-h, --help Prints help information
|
-h, --help Prints help information
|
||||||
-a, --alive Indicates whether or not the animal is alive
|
-a, --alive Indicates whether or not the animal is alive
|
||||||
-n, --name <VALUE>
|
-n, --name <VALUE>
|
||||||
--agility <VALUE> 10 The agility between 0 and 100
|
--agility <VALUE> 10 The agility between 0 and 100
|
||||||
-c <CHILDREN> The number of children the lion has
|
-c <CHILDREN> The number of children the lion has
|
||||||
|
-d <DAY> Monday, Thursday The days the lion goes hunting
|
@ -10,11 +10,12 @@ ARGUMENTS:
|
|||||||
|
|
||||||
OPTIONS:
|
OPTIONS:
|
||||||
DEFAULT
|
DEFAULT
|
||||||
-h, --help Prints help information
|
-h, --help Prints help information
|
||||||
-a, --alive Indicates whether or not the animal is alive
|
-a, --alive Indicates whether or not the animal is alive
|
||||||
-n, --name <VALUE>
|
-n, --name <VALUE>
|
||||||
--agility <VALUE> 10 The agility between 0 and 100
|
--agility <VALUE> 10 The agility between 0 and 100
|
||||||
-c <CHILDREN> The number of children the lion has
|
-c <CHILDREN> The number of children the lion has
|
||||||
|
-d <DAY> Monday, Thursday The days the lion goes hunting
|
||||||
|
|
||||||
COMMANDS:
|
COMMANDS:
|
||||||
giraffe <LENGTH> The giraffe command
|
giraffe <LENGTH> The giraffe command
|
@ -8,5 +8,7 @@ ARGUMENTS:
|
|||||||
<TEETH> The number of teeth the lion has
|
<TEETH> The number of teeth the lion has
|
||||||
|
|
||||||
OPTIONS:
|
OPTIONS:
|
||||||
-h, --help Prints help information
|
DEFAULT
|
||||||
-c <CHILDREN> The number of children the lion has
|
-h, --help Prints help information
|
||||||
|
-c <CHILDREN> The number of children the lion has
|
||||||
|
-d <DAY> Monday, Thursday The days the lion goes hunting
|
@ -396,6 +396,50 @@ public sealed partial class CommandAppTests
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Should_Assign_Array_Default_Value_To_Command_Option()
|
||||||
|
{
|
||||||
|
// Given
|
||||||
|
var app = new CommandAppTester();
|
||||||
|
app.SetDefaultCommand<GenericCommand<OptionWithArrayOfEnumDefaultValueSettings>>();
|
||||||
|
app.Configure(config =>
|
||||||
|
{
|
||||||
|
config.PropagateExceptions();
|
||||||
|
});
|
||||||
|
|
||||||
|
// When
|
||||||
|
var result = app.Run(Array.Empty<string>());
|
||||||
|
|
||||||
|
// Then
|
||||||
|
result.ExitCode.ShouldBe(0);
|
||||||
|
result.Settings.ShouldBeOfType<OptionWithArrayOfEnumDefaultValueSettings>().And(settings =>
|
||||||
|
{
|
||||||
|
settings.Days.ShouldBe(new[] { DayOfWeek.Sunday, DayOfWeek.Saturday });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Should_Assign_Array_Default_Value_To_Command_Option_Using_Converter_If_Necessary()
|
||||||
|
{
|
||||||
|
// Given
|
||||||
|
var app = new CommandAppTester();
|
||||||
|
app.SetDefaultCommand<GenericCommand<OptionWithArrayOfStringDefaultValueAndTypeConverterSettings>>();
|
||||||
|
app.Configure(config =>
|
||||||
|
{
|
||||||
|
config.PropagateExceptions();
|
||||||
|
});
|
||||||
|
|
||||||
|
// When
|
||||||
|
var result = app.Run(Array.Empty<string>());
|
||||||
|
|
||||||
|
// Then
|
||||||
|
result.ExitCode.ShouldBe(0);
|
||||||
|
result.Settings.ShouldBeOfType<OptionWithArrayOfStringDefaultValueAndTypeConverterSettings>().And(settings =>
|
||||||
|
{
|
||||||
|
settings.Numbers.ShouldBe(new[] { 2, 3 });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void Should_Throw_If_Required_Argument_Have_Default_Value()
|
public void Should_Throw_If_Required_Argument_Have_Default_Value()
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user