mirror of
https://github.com/nsnail/spectre.console.git
synced 2025-07-02 19:08:15 +08:00
Add Spectre.Cli to Spectre.Console
* Renames Spectre.Cli to Spectre.Console.Cli. * Now uses Verify with Spectre.Console.Cli tests. * Removes some duplicate definitions. Closes #168
This commit is contained in:

committed by
Patrik Svensson

parent
0bbf9b81a9
commit
0ae419326d
19
src/Spectre.Console.Tests/Constants.cs
Normal file
19
src/Spectre.Console.Tests/Constants.cs
Normal file
@ -0,0 +1,19 @@
|
||||
namespace Spectre.Console.Tests
|
||||
{
|
||||
public static class Constants
|
||||
{
|
||||
public static string[] VersionCommand { get; } =
|
||||
new[]
|
||||
{
|
||||
Spectre.Console.Cli.Internal.Constants.Commands.Branch,
|
||||
Spectre.Console.Cli.Internal.Constants.Commands.Version,
|
||||
};
|
||||
|
||||
public static string[] XmlDocCommand { get; } =
|
||||
new[]
|
||||
{
|
||||
Spectre.Console.Cli.Internal.Constants.Commands.Branch,
|
||||
Spectre.Console.Cli.Internal.Constants.Commands.XmlDoc,
|
||||
};
|
||||
}
|
||||
}
|
49
src/Spectre.Console.Tests/Data/Commands/AnimalCommand.cs
Normal file
49
src/Spectre.Console.Tests/Data/Commands/AnimalCommand.cs
Normal file
@ -0,0 +1,49 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Spectre.Console.Cli;
|
||||
using SystemConsole = System.Console;
|
||||
|
||||
namespace Spectre.Console.Tests.Data
|
||||
{
|
||||
public abstract class AnimalCommand<TSettings> : Command<TSettings>
|
||||
where TSettings : CommandSettings
|
||||
{
|
||||
protected void DumpSettings(CommandContext context, TSettings settings)
|
||||
{
|
||||
if (context == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(context));
|
||||
}
|
||||
|
||||
if (settings == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(settings));
|
||||
}
|
||||
|
||||
var properties = settings.GetType().GetProperties();
|
||||
foreach (var group in properties.GroupBy(x => x.DeclaringType).Reverse())
|
||||
{
|
||||
SystemConsole.WriteLine();
|
||||
SystemConsole.ForegroundColor = ConsoleColor.Yellow;
|
||||
SystemConsole.WriteLine(group.Key.FullName);
|
||||
SystemConsole.ResetColor();
|
||||
|
||||
foreach (var property in group)
|
||||
{
|
||||
SystemConsole.WriteLine($" {property.Name} = {property.GetValue(settings)}");
|
||||
}
|
||||
}
|
||||
|
||||
if (context.Remaining.Raw.Count > 0)
|
||||
{
|
||||
SystemConsole.WriteLine();
|
||||
SystemConsole.ForegroundColor = ConsoleColor.Yellow;
|
||||
SystemConsole.WriteLine("Remaining:");
|
||||
SystemConsole.ResetColor();
|
||||
SystemConsole.WriteLine(string.Join(", ", context.Remaining));
|
||||
}
|
||||
|
||||
SystemConsole.WriteLine();
|
||||
}
|
||||
}
|
||||
}
|
13
src/Spectre.Console.Tests/Data/Commands/CatCommand.cs
Normal file
13
src/Spectre.Console.Tests/Data/Commands/CatCommand.cs
Normal file
@ -0,0 +1,13 @@
|
||||
using Spectre.Console.Cli;
|
||||
|
||||
namespace Spectre.Console.Tests.Data
|
||||
{
|
||||
public class CatCommand : AnimalCommand<CatSettings>
|
||||
{
|
||||
public override int Execute(CommandContext context, CatSettings settings)
|
||||
{
|
||||
DumpSettings(context, settings);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
36
src/Spectre.Console.Tests/Data/Commands/DogCommand.cs
Normal file
36
src/Spectre.Console.Tests/Data/Commands/DogCommand.cs
Normal file
@ -0,0 +1,36 @@
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using Spectre.Console.Cli;
|
||||
|
||||
namespace Spectre.Console.Tests.Data
|
||||
{
|
||||
[Description("The dog command.")]
|
||||
public class DogCommand : AnimalCommand<DogSettings>
|
||||
{
|
||||
public override ValidationResult Validate(CommandContext context, DogSettings settings)
|
||||
{
|
||||
if (context is null)
|
||||
{
|
||||
throw new System.ArgumentNullException(nameof(context));
|
||||
}
|
||||
|
||||
if (settings is null)
|
||||
{
|
||||
throw new System.ArgumentNullException(nameof(settings));
|
||||
}
|
||||
|
||||
if (settings.Age > 100 && !context.Remaining.Raw.Contains("zombie"))
|
||||
{
|
||||
return ValidationResult.Error("Dog is too old...");
|
||||
}
|
||||
|
||||
return base.Validate(context, settings);
|
||||
}
|
||||
|
||||
public override int Execute(CommandContext context, DogSettings settings)
|
||||
{
|
||||
DumpSettings(context, settings);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
12
src/Spectre.Console.Tests/Data/Commands/EmptyCommand.cs
Normal file
12
src/Spectre.Console.Tests/Data/Commands/EmptyCommand.cs
Normal file
@ -0,0 +1,12 @@
|
||||
using Spectre.Console.Cli;
|
||||
|
||||
namespace Spectre.Console.Tests.Data
|
||||
{
|
||||
public sealed class EmptyCommand : Command<EmptyCommandSettings>
|
||||
{
|
||||
public override int Execute(CommandContext context, EmptyCommandSettings settings)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
13
src/Spectre.Console.Tests/Data/Commands/GenericCommand.cs
Normal file
13
src/Spectre.Console.Tests/Data/Commands/GenericCommand.cs
Normal file
@ -0,0 +1,13 @@
|
||||
using Spectre.Console.Cli;
|
||||
|
||||
namespace Spectre.Console.Tests.Data
|
||||
{
|
||||
public sealed class GenericCommand<TSettings> : Command<TSettings>
|
||||
where TSettings : CommandSettings
|
||||
{
|
||||
public override int Execute(CommandContext context, TSettings settings)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
14
src/Spectre.Console.Tests/Data/Commands/GiraffeCommand.cs
Normal file
14
src/Spectre.Console.Tests/Data/Commands/GiraffeCommand.cs
Normal file
@ -0,0 +1,14 @@
|
||||
using System.ComponentModel;
|
||||
using Spectre.Console.Cli;
|
||||
|
||||
namespace Spectre.Console.Tests.Data
|
||||
{
|
||||
[Description("The giraffe command.")]
|
||||
public sealed class GiraffeCommand : Command<GiraffeSettings>
|
||||
{
|
||||
public override int Execute(CommandContext context, GiraffeSettings settings)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
15
src/Spectre.Console.Tests/Data/Commands/HorseCommand.cs
Normal file
15
src/Spectre.Console.Tests/Data/Commands/HorseCommand.cs
Normal file
@ -0,0 +1,15 @@
|
||||
using System.ComponentModel;
|
||||
using Spectre.Console.Cli;
|
||||
|
||||
namespace Spectre.Console.Tests.Data
|
||||
{
|
||||
[Description("The horse command.")]
|
||||
public class HorseCommand : AnimalCommand<MammalSettings>
|
||||
{
|
||||
public override int Execute(CommandContext context, MammalSettings settings)
|
||||
{
|
||||
DumpSettings(context, settings);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
using System;
|
||||
using Spectre.Console.Cli;
|
||||
|
||||
namespace Spectre.Console.Tests.Data
|
||||
{
|
||||
public sealed class InterceptingCommand<TSettings> : Command<TSettings>
|
||||
where TSettings : CommandSettings
|
||||
{
|
||||
private readonly Action<CommandContext, TSettings> _action;
|
||||
|
||||
public InterceptingCommand(Action<CommandContext, TSettings> action)
|
||||
{
|
||||
_action = action ?? throw new ArgumentNullException(nameof(action));
|
||||
}
|
||||
|
||||
public override int Execute(CommandContext context, TSettings settings)
|
||||
{
|
||||
_action(context, settings);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
12
src/Spectre.Console.Tests/Data/Commands/InvalidCommand.cs
Normal file
12
src/Spectre.Console.Tests/Data/Commands/InvalidCommand.cs
Normal file
@ -0,0 +1,12 @@
|
||||
using Spectre.Console.Cli;
|
||||
|
||||
namespace Spectre.Console.Tests.Data
|
||||
{
|
||||
public sealed class InvalidCommand : Command<InvalidSettings>
|
||||
{
|
||||
public override int Execute(CommandContext context, InvalidSettings settings)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
14
src/Spectre.Console.Tests/Data/Commands/LionCommand.cs
Normal file
14
src/Spectre.Console.Tests/Data/Commands/LionCommand.cs
Normal file
@ -0,0 +1,14 @@
|
||||
using System.ComponentModel;
|
||||
using Spectre.Console.Cli;
|
||||
|
||||
namespace Spectre.Console.Tests.Data
|
||||
{
|
||||
[Description("The lion command.")]
|
||||
public class LionCommand : AnimalCommand<LionSettings>
|
||||
{
|
||||
public override int Execute(CommandContext context, LionSettings settings)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
using Spectre.Console.Cli;
|
||||
|
||||
namespace Spectre.Console.Tests.Data
|
||||
{
|
||||
public class OptionVectorCommand : Command<OptionVectorSettings>
|
||||
{
|
||||
public override int Execute(CommandContext context, OptionVectorSettings settings)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
17
src/Spectre.Console.Tests/Data/Commands/ThrowingCommand.cs
Normal file
17
src/Spectre.Console.Tests/Data/Commands/ThrowingCommand.cs
Normal file
@ -0,0 +1,17 @@
|
||||
using System;
|
||||
using Spectre.Console.Cli;
|
||||
|
||||
namespace Spectre.Console.Tests.Data
|
||||
{
|
||||
public sealed class ThrowingCommand : Command<ThrowingCommandSettings>
|
||||
{
|
||||
public override int Execute(CommandContext context, ThrowingCommandSettings settings)
|
||||
{
|
||||
throw new InvalidOperationException("W00t?");
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class ThrowingCommandSettings : CommandSettings
|
||||
{
|
||||
}
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
using System.ComponentModel;
|
||||
using System.Globalization;
|
||||
|
||||
namespace Spectre.Console.Tests.Data
|
||||
{
|
||||
public sealed class CatAgilityConverter : TypeConverter
|
||||
{
|
||||
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
|
||||
{
|
||||
if (value is string stringValue)
|
||||
{
|
||||
return stringValue.Length;
|
||||
}
|
||||
|
||||
return base.ConvertFrom(context, culture, value);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
using System.ComponentModel;
|
||||
using System.Globalization;
|
||||
|
||||
namespace Spectre.Console.Tests.Data
|
||||
{
|
||||
public sealed class StringToIntegerConverter : TypeConverter
|
||||
{
|
||||
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
|
||||
{
|
||||
if (value is string stringValue)
|
||||
{
|
||||
return int.Parse(stringValue, CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
return base.ConvertFrom(context, culture, value);
|
||||
}
|
||||
}
|
||||
}
|
18
src/Spectre.Console.Tests/Data/Settings/AnimalSettings.cs
Normal file
18
src/Spectre.Console.Tests/Data/Settings/AnimalSettings.cs
Normal file
@ -0,0 +1,18 @@
|
||||
using System.ComponentModel;
|
||||
using Spectre.Console.Cli;
|
||||
|
||||
namespace Spectre.Console.Tests.Data
|
||||
{
|
||||
public abstract class AnimalSettings : CommandSettings
|
||||
{
|
||||
[CommandOption("-a|--alive|--not-dead")]
|
||||
[Description("Indicates whether or not the animal is alive.")]
|
||||
public bool IsAlive { get; set; }
|
||||
|
||||
[CommandArgument(1, "[LEGS]")]
|
||||
[Description("The number of legs.")]
|
||||
[EvenNumberValidator("Animals must have an even number of legs.")]
|
||||
[PositiveNumberValidator("Number of legs must be greater than 0.")]
|
||||
public int Legs { get; set; }
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Spectre.Console.Cli;
|
||||
|
||||
namespace Spectre.Console.Tests.Data
|
||||
{
|
||||
public class ArgumentVectorSettings : CommandSettings
|
||||
{
|
||||
[CommandArgument(0, "<Foos>")]
|
||||
[SuppressMessage("Performance", "CA1819:Properties should not return arrays")]
|
||||
public string[] Foo { get; set; }
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
using System.ComponentModel;
|
||||
using Spectre.Console.Cli;
|
||||
|
||||
namespace Spectre.Console.Tests.Data
|
||||
{
|
||||
public class BarCommandSettings : FooCommandSettings
|
||||
{
|
||||
[CommandArgument(0, "<CORGI>")]
|
||||
[Description("The corgi value.")]
|
||||
public string Corgi { get; set; }
|
||||
}
|
||||
}
|
15
src/Spectre.Console.Tests/Data/Settings/CatSettings.cs
Normal file
15
src/Spectre.Console.Tests/Data/Settings/CatSettings.cs
Normal file
@ -0,0 +1,15 @@
|
||||
using System.ComponentModel;
|
||||
using Spectre.Console.Cli;
|
||||
|
||||
namespace Spectre.Console.Tests.Data
|
||||
{
|
||||
public class CatSettings : MammalSettings
|
||||
{
|
||||
[CommandOption("--agility <VALUE>")]
|
||||
[TypeConverter(typeof(CatAgilityConverter))]
|
||||
[DefaultValue(10)]
|
||||
[Description("The agility between 0 and 100.")]
|
||||
[PositiveNumberValidator("Agility cannot be negative.")]
|
||||
public int Agility { get; set; }
|
||||
}
|
||||
}
|
23
src/Spectre.Console.Tests/Data/Settings/DogSettings.cs
Normal file
23
src/Spectre.Console.Tests/Data/Settings/DogSettings.cs
Normal file
@ -0,0 +1,23 @@
|
||||
using Spectre.Console.Cli;
|
||||
|
||||
namespace Spectre.Console.Tests.Data
|
||||
{
|
||||
public sealed class DogSettings : MammalSettings
|
||||
{
|
||||
[CommandArgument(0, "<AGE>")]
|
||||
public int Age { get; set; }
|
||||
|
||||
[CommandOption("-g|--good-boy")]
|
||||
public bool GoodBoy { get; set; }
|
||||
|
||||
public override ValidationResult Validate()
|
||||
{
|
||||
if (Name == "Tiger")
|
||||
{
|
||||
return ValidationResult.Error("Tiger is not a dog name!");
|
||||
}
|
||||
|
||||
return ValidationResult.Success();
|
||||
}
|
||||
}
|
||||
}
|
8
src/Spectre.Console.Tests/Data/Settings/EmptySettings.cs
Normal file
8
src/Spectre.Console.Tests/Data/Settings/EmptySettings.cs
Normal file
@ -0,0 +1,8 @@
|
||||
using Spectre.Console.Cli;
|
||||
|
||||
namespace Spectre.Console.Tests.Data
|
||||
{
|
||||
public sealed class EmptySettings : CommandSettings
|
||||
{
|
||||
}
|
||||
}
|
12
src/Spectre.Console.Tests/Data/Settings/FooSettings.cs
Normal file
12
src/Spectre.Console.Tests/Data/Settings/FooSettings.cs
Normal file
@ -0,0 +1,12 @@
|
||||
using System.ComponentModel;
|
||||
using Spectre.Console.Cli;
|
||||
|
||||
namespace Spectre.Console.Tests.Data
|
||||
{
|
||||
public class FooCommandSettings : CommandSettings
|
||||
{
|
||||
[CommandArgument(0, "[QUX]")]
|
||||
[Description("The qux value.")]
|
||||
public string Qux { get; set; }
|
||||
}
|
||||
}
|
12
src/Spectre.Console.Tests/Data/Settings/GiraffeSettings.cs
Normal file
12
src/Spectre.Console.Tests/Data/Settings/GiraffeSettings.cs
Normal file
@ -0,0 +1,12 @@
|
||||
using System.ComponentModel;
|
||||
using Spectre.Console.Cli;
|
||||
|
||||
namespace Spectre.Console.Tests.Data
|
||||
{
|
||||
public sealed class GiraffeSettings : MammalSettings
|
||||
{
|
||||
[CommandArgument(0, "<LENGTH>")]
|
||||
[Description("The option description.")]
|
||||
public int Length { get; set; }
|
||||
}
|
||||
}
|
10
src/Spectre.Console.Tests/Data/Settings/InvalidSettings.cs
Normal file
10
src/Spectre.Console.Tests/Data/Settings/InvalidSettings.cs
Normal file
@ -0,0 +1,10 @@
|
||||
using Spectre.Console.Cli;
|
||||
|
||||
namespace Spectre.Console.Tests.Data
|
||||
{
|
||||
public sealed class InvalidSettings : CommandSettings
|
||||
{
|
||||
[CommandOption("-f|--foo [BAR]")]
|
||||
public string Value { get; set; }
|
||||
}
|
||||
}
|
16
src/Spectre.Console.Tests/Data/Settings/LionSettings.cs
Normal file
16
src/Spectre.Console.Tests/Data/Settings/LionSettings.cs
Normal file
@ -0,0 +1,16 @@
|
||||
using System.ComponentModel;
|
||||
using Spectre.Console.Cli;
|
||||
|
||||
namespace Spectre.Console.Tests.Data
|
||||
{
|
||||
public class LionSettings : CatSettings
|
||||
{
|
||||
[CommandArgument(0, "<TEETH>")]
|
||||
[Description("The number of teeth the lion has.")]
|
||||
public int Teeth { get; set; }
|
||||
|
||||
[CommandOption("-c <CHILDREN>")]
|
||||
[Description("The number of children the lion has.")]
|
||||
public int Children { get; set; }
|
||||
}
|
||||
}
|
10
src/Spectre.Console.Tests/Data/Settings/MammalSettings.cs
Normal file
10
src/Spectre.Console.Tests/Data/Settings/MammalSettings.cs
Normal file
@ -0,0 +1,10 @@
|
||||
using Spectre.Console.Cli;
|
||||
|
||||
namespace Spectre.Console.Tests.Data
|
||||
{
|
||||
public class MammalSettings : AnimalSettings
|
||||
{
|
||||
[CommandOption("-n|-p|--name|--pet-name <VALUE>")]
|
||||
public string Name { get; set; }
|
||||
}
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Spectre.Console.Cli;
|
||||
|
||||
namespace Spectre.Console.Tests.Data
|
||||
{
|
||||
public class MultipleArgumentVectorSettings : CommandSettings
|
||||
{
|
||||
[CommandArgument(0, "<Foos>")]
|
||||
[SuppressMessage("Performance", "CA1819:Properties should not return arrays")]
|
||||
public string[] Foo { get; set; }
|
||||
|
||||
[CommandArgument(0, "<Bars>")]
|
||||
[SuppressMessage("Performance", "CA1819:Properties should not return arrays")]
|
||||
public string[] Bar { get; set; }
|
||||
}
|
||||
|
||||
public class MultipleArgumentVectorSpecifiedFirstSettings : CommandSettings
|
||||
{
|
||||
[CommandArgument(0, "<Foos>")]
|
||||
[SuppressMessage("Performance", "CA1819:Properties should not return arrays")]
|
||||
public string[] Foo { get; set; }
|
||||
|
||||
[CommandArgument(1, "<Bar>")]
|
||||
public string Bar { get; set; }
|
||||
}
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Spectre.Console.Cli;
|
||||
|
||||
namespace Spectre.Console.Tests.Data
|
||||
{
|
||||
public class OptionVectorSettings : CommandSettings
|
||||
{
|
||||
[CommandOption("--foo")]
|
||||
[SuppressMessage("Performance", "CA1819:Properties should not return arrays")]
|
||||
public string[] Foo { get; set; }
|
||||
|
||||
[CommandOption("--bar")]
|
||||
[SuppressMessage("Performance", "CA1819:Properties should not return arrays")]
|
||||
public int[] Bar { get; set; }
|
||||
}
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
using System.ComponentModel;
|
||||
using Spectre.Console.Cli;
|
||||
|
||||
namespace Spectre.Console.Tests.Data
|
||||
{
|
||||
public sealed class OptionalArgumentWithDefaultValueSettings : CommandSettings
|
||||
{
|
||||
[CommandArgument(0, "[GREETING]")]
|
||||
[DefaultValue("Hello World")]
|
||||
public string Greeting { get; set; }
|
||||
}
|
||||
|
||||
public sealed class OptionalArgumentWithDefaultValueAndTypeConverterSettings : CommandSettings
|
||||
{
|
||||
[CommandArgument(0, "[GREETING]")]
|
||||
[DefaultValue("5")]
|
||||
[TypeConverter(typeof(StringToIntegerConverter))]
|
||||
public int Greeting { get; set; }
|
||||
}
|
||||
|
||||
public sealed class RequiredArgumentWithDefaultValueSettings : CommandSettings
|
||||
{
|
||||
[CommandArgument(0, "<GREETING>")]
|
||||
[DefaultValue("Hello World")]
|
||||
public string Greeting { get; set; }
|
||||
}
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
using Spectre.Console.Cli;
|
||||
|
||||
namespace Spectre.Console.Tests.Data
|
||||
{
|
||||
public sealed class StringOptionSettings : CommandSettings
|
||||
{
|
||||
[CommandOption("-f|--foo")]
|
||||
public string Foo { get; set; }
|
||||
}
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
using System;
|
||||
using Spectre.Console.Cli;
|
||||
|
||||
namespace Spectre.Console.Tests.Data
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Property, AllowMultiple = true)]
|
||||
public sealed class EvenNumberValidatorAttribute : ParameterValidationAttribute
|
||||
{
|
||||
public EvenNumberValidatorAttribute(string errorMessage)
|
||||
: base(errorMessage)
|
||||
{
|
||||
}
|
||||
|
||||
public override ValidationResult Validate(ICommandParameterInfo info, object value)
|
||||
{
|
||||
if (value is int integer)
|
||||
{
|
||||
if (integer % 2 == 0)
|
||||
{
|
||||
return ValidationResult.Success();
|
||||
}
|
||||
|
||||
return ValidationResult.Error($"Number is not even ({info?.PropertyName}).");
|
||||
}
|
||||
|
||||
throw new InvalidOperationException($"Parameter is not a number ({info?.PropertyName}).");
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
using System;
|
||||
using Spectre.Console.Cli;
|
||||
|
||||
namespace Spectre.Console.Tests.Data
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Property, AllowMultiple = true)]
|
||||
public sealed class PositiveNumberValidatorAttribute : ParameterValidationAttribute
|
||||
{
|
||||
public PositiveNumberValidatorAttribute(string errorMessage)
|
||||
: base(errorMessage)
|
||||
{
|
||||
}
|
||||
|
||||
public override ValidationResult Validate(ICommandParameterInfo info, object value)
|
||||
{
|
||||
if (value is int integer)
|
||||
{
|
||||
if (integer > 0)
|
||||
{
|
||||
return ValidationResult.Success();
|
||||
}
|
||||
|
||||
return ValidationResult.Error($"Number is not greater than 0 ({info?.PropertyName}).");
|
||||
}
|
||||
|
||||
throw new InvalidOperationException($"Parameter is not a number ({info?.PropertyName}).");
|
||||
}
|
||||
}
|
||||
}
|
@ -1,46 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using Xunit.Sdk;
|
||||
|
||||
namespace Spectre.Console.Tests
|
||||
{
|
||||
public sealed class EmbeddedResourceDataAttribute : DataAttribute
|
||||
{
|
||||
private readonly string _args;
|
||||
|
||||
public EmbeddedResourceDataAttribute(string args)
|
||||
{
|
||||
_args = args ?? throw new ArgumentNullException(nameof(args));
|
||||
}
|
||||
|
||||
public override IEnumerable<object[]> GetData(MethodInfo testMethod)
|
||||
{
|
||||
var result = new object[1];
|
||||
result[0] = ReadManifestData(_args);
|
||||
return new[] { result };
|
||||
}
|
||||
|
||||
public static string ReadManifestData(string resourceName)
|
||||
{
|
||||
if (resourceName is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(resourceName));
|
||||
}
|
||||
|
||||
using (var stream = ResourceReader.LoadResourceStream(resourceName))
|
||||
{
|
||||
if (stream == null)
|
||||
{
|
||||
throw new InvalidOperationException("Could not load manifest resource stream.");
|
||||
}
|
||||
|
||||
using (var reader = new StreamReader(stream))
|
||||
{
|
||||
return reader.ReadToEnd().NormalizeLineEndings();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
USAGE:
|
||||
myapp animal [LEGS] [OPTIONS] <COMMAND>
|
||||
|
||||
EXAMPLES:
|
||||
myapp animal --help
|
||||
|
||||
ARGUMENTS:
|
||||
[LEGS] The number of legs
|
||||
|
||||
OPTIONS:
|
||||
-h, --help Prints help information
|
||||
-a, --alive Indicates whether or not the animal is alive
|
||||
|
||||
COMMANDS:
|
||||
dog <AGE> The dog command
|
||||
horse The horse command
|
@ -0,0 +1,14 @@
|
||||
USAGE:
|
||||
myapp cat [LEGS] [OPTIONS] <COMMAND>
|
||||
|
||||
ARGUMENTS:
|
||||
[LEGS] The number of legs
|
||||
|
||||
OPTIONS:
|
||||
-h, --help Prints help information
|
||||
-a, --alive Indicates whether or not the animal is alive
|
||||
-n, --name <VALUE>
|
||||
--agility <VALUE> The agility between 0 and 100
|
||||
|
||||
COMMANDS:
|
||||
lion <TEETH> The lion command
|
@ -0,0 +1,13 @@
|
||||
USAGE:
|
||||
myapp <TEETH> [LEGS] [OPTIONS]
|
||||
|
||||
ARGUMENTS:
|
||||
[LEGS] The number of legs
|
||||
<TEETH> The number of teeth the lion has
|
||||
|
||||
OPTIONS:
|
||||
-h, --help Prints help information
|
||||
-a, --alive Indicates whether or not the animal is alive
|
||||
-n, --name <VALUE>
|
||||
--agility <VALUE> The agility between 0 and 100
|
||||
-c <CHILDREN> The number of children the lion has
|
@ -0,0 +1,9 @@
|
||||
USAGE:
|
||||
myapp cat [LEGS] lion <TEETH> [OPTIONS]
|
||||
|
||||
ARGUMENTS:
|
||||
<TEETH> The number of teeth the lion has
|
||||
|
||||
OPTIONS:
|
||||
-h, --help Prints help information
|
||||
-c <CHILDREN> The number of children the lion has
|
@ -0,0 +1,11 @@
|
||||
USAGE:
|
||||
myapp [OPTIONS] <COMMAND>
|
||||
|
||||
OPTIONS:
|
||||
-h, --help Prints help information
|
||||
-v, --version Prints version information
|
||||
|
||||
COMMANDS:
|
||||
dog <AGE> The dog command
|
||||
horse The horse command
|
||||
giraffe <LENGTH> The giraffe command
|
@ -0,0 +1,14 @@
|
||||
USAGE:
|
||||
myapp [OPTIONS] <COMMAND>
|
||||
|
||||
EXAMPLES:
|
||||
myapp dog --name Rufus --age 12 --good-boy
|
||||
myapp horse --name Brutus
|
||||
|
||||
OPTIONS:
|
||||
-h, --help Prints help information
|
||||
-v, --version Prints version information
|
||||
|
||||
COMMANDS:
|
||||
dog <AGE> The dog command
|
||||
horse The horse command
|
@ -0,0 +1,13 @@
|
||||
USAGE:
|
||||
myapp [OPTIONS] <COMMAND>
|
||||
|
||||
EXAMPLES:
|
||||
myapp animal dog --name Rufus --age 12 --good-boy
|
||||
myapp animal horse --name Brutus
|
||||
|
||||
OPTIONS:
|
||||
-h, --help Prints help information
|
||||
-v, --version Prints version information
|
||||
|
||||
COMMANDS:
|
||||
animal The animal command
|
@ -0,0 +1,14 @@
|
||||
USAGE:
|
||||
myapp [OPTIONS] <COMMAND>
|
||||
|
||||
EXAMPLES:
|
||||
myapp dog --name Rufus --age 12 --good-boy
|
||||
myapp horse --name Brutus
|
||||
|
||||
OPTIONS:
|
||||
-h, --help Prints help information
|
||||
-v, --version Prints version information
|
||||
|
||||
COMMANDS:
|
||||
dog <AGE> The dog command
|
||||
horse The horse command
|
@ -0,0 +1,16 @@
|
||||
USAGE:
|
||||
myapp <TEETH> [LEGS] [OPTIONS]
|
||||
|
||||
EXAMPLES:
|
||||
myapp 12 -c 3
|
||||
|
||||
ARGUMENTS:
|
||||
[LEGS] The number of legs
|
||||
<TEETH> The number of teeth the lion has
|
||||
|
||||
OPTIONS:
|
||||
-h, --help Prints help information
|
||||
-a, --alive Indicates whether or not the animal is alive
|
||||
-n, --name <VALUE>
|
||||
--agility <VALUE> The agility between 0 and 100
|
||||
-c <CHILDREN> The number of children the lion has
|
@ -0,0 +1,10 @@
|
||||
USAGE:
|
||||
myapp [OPTIONS] <COMMAND>
|
||||
|
||||
OPTIONS:
|
||||
-h, --help Prints help information
|
||||
-v, --version Prints version information
|
||||
|
||||
COMMANDS:
|
||||
dog <AGE> The dog command
|
||||
horse The horse command
|
@ -0,0 +1,4 @@
|
||||
Error: Flags cannot be assigned a value.
|
||||
|
||||
dog --alive foo
|
||||
^^^^^^^ Can't assign value
|
@ -0,0 +1,4 @@
|
||||
Error: Flags cannot be assigned a value.
|
||||
|
||||
dog -a foo
|
||||
^^ Can't assign value
|
@ -0,0 +1,4 @@
|
||||
Error: Short option does not have a valid name.
|
||||
|
||||
dog -f0o
|
||||
^ Not a valid name for a short option
|
@ -0,0 +1,4 @@
|
||||
Error: Invalid long option name.
|
||||
|
||||
dog --f€oo
|
||||
^ Invalid character
|
@ -0,0 +1,4 @@
|
||||
Error: Invalid long option name.
|
||||
|
||||
dog --
|
||||
^^ Did you forget the option name?
|
@ -0,0 +1,4 @@
|
||||
Error: Invalid long option name.
|
||||
|
||||
dog --f
|
||||
^^^ Did you mean -f?
|
@ -0,0 +1,4 @@
|
||||
Error: Invalid long option name.
|
||||
|
||||
dog --1foo
|
||||
^^^^^^ Option names cannot start with a digit
|
@ -0,0 +1,4 @@
|
||||
Error: Could not match 'baz' with an argument.
|
||||
|
||||
giraffe foo bar baz
|
||||
^^^ Could not match to argument
|
@ -0,0 +1,4 @@
|
||||
Error: Option 'name' is defined but no value has been provided.
|
||||
|
||||
dog --name
|
||||
^^^^^^ No value provided
|
@ -0,0 +1,4 @@
|
||||
Error: Option 'name' is defined but no value has been provided.
|
||||
|
||||
dog -n
|
||||
^^ No value provided
|
@ -0,0 +1,4 @@
|
||||
Error: Expected an option value.
|
||||
|
||||
dog --foo:
|
||||
^ Did you forget the option value?
|
@ -0,0 +1,4 @@
|
||||
Error: Expected an option value.
|
||||
|
||||
dog --foo=
|
||||
^ Did you forget the option value?
|
@ -0,0 +1,4 @@
|
||||
Error: Expected an option value.
|
||||
|
||||
dog -f:
|
||||
^ Did you forget the option value?
|
@ -0,0 +1,4 @@
|
||||
Error: Expected an option value.
|
||||
|
||||
dog -f=
|
||||
^ Did you forget the option value?
|
@ -0,0 +1,4 @@
|
||||
Error: Option does not have a name.
|
||||
|
||||
dog -
|
||||
^ Did you forget the option name?
|
@ -0,0 +1,4 @@
|
||||
Error: Unexpected option 'foo'.
|
||||
|
||||
--foo
|
||||
^^^^^ Did you forget the command?
|
@ -0,0 +1,4 @@
|
||||
Error: Unexpected option 'f'.
|
||||
|
||||
-f
|
||||
^^ Did you forget the command?
|
@ -0,0 +1,4 @@
|
||||
Error: Unknown command 'other'.
|
||||
|
||||
empty other
|
||||
^^^^^ No such command
|
@ -0,0 +1,4 @@
|
||||
Error: Unknown command 'cat'.
|
||||
|
||||
cat 14
|
||||
^^^ No such command
|
@ -0,0 +1,4 @@
|
||||
Error: Unknown command 'bat'.
|
||||
|
||||
dog bat
|
||||
^^^ Did you mean 'cat'?
|
@ -0,0 +1,4 @@
|
||||
Error: Unknown command 'bat'.
|
||||
|
||||
bat
|
||||
^^^ Did you mean 'cat'?
|
@ -0,0 +1,4 @@
|
||||
Error: Unknown command 'bat'.
|
||||
|
||||
foo qux bat
|
||||
^^^ Did you mean 'bar'?
|
@ -0,0 +1,4 @@
|
||||
Error: Unknown command 'bat'.
|
||||
|
||||
dog bat 14
|
||||
^^^ Did you mean 'cat'?
|
@ -0,0 +1,4 @@
|
||||
Error: Unknown command 'bat'.
|
||||
|
||||
qux bat
|
||||
^^^ Did you mean 'bar'?
|
@ -0,0 +1,4 @@
|
||||
Error: Unknown command 'bat'.
|
||||
|
||||
bat 14
|
||||
^^^ Did you mean 'cat'?
|
@ -0,0 +1,4 @@
|
||||
Error: Unknown option 'unknown'.
|
||||
|
||||
dog --unknown
|
||||
^^^^^^^^^ Unknown option
|
@ -0,0 +1,4 @@
|
||||
Error: Unknown option 'u'.
|
||||
|
||||
dog -u
|
||||
^^ Unknown option
|
@ -0,0 +1,4 @@
|
||||
Error: Encountered unterminated quoted string 'Rufus'.
|
||||
|
||||
--name "Rufus
|
||||
^^^^^^ Did you forget the closing quotation mark?
|
@ -0,0 +1,37 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Model>
|
||||
<!--ANIMAL-->
|
||||
<Command Name="animal" IsBranch="true" Settings="Spectre.Console.Tests.Data.AnimalSettings">
|
||||
<Parameters>
|
||||
<Argument Name="LEGS" Position="0" Required="false" Kind="scalar" ClrType="System.Int32">
|
||||
<Description>The number of legs.</Description>
|
||||
<Validators>
|
||||
<Validator ClrType="Spectre.Console.Tests.Data.EvenNumberValidatorAttribute" Message="Animals must have an even number of legs." />
|
||||
<Validator ClrType="Spectre.Console.Tests.Data.PositiveNumberValidatorAttribute" Message="Number of legs must be greater than 0." />
|
||||
</Validators>
|
||||
</Argument>
|
||||
<Option Short="a" Long="alive,not-dead" Value="NULL" Required="false" Kind="flag" ClrType="System.Boolean">
|
||||
<Description>Indicates whether or not the animal is alive.</Description>
|
||||
</Option>
|
||||
</Parameters>
|
||||
<!--MAMMAL-->
|
||||
<Command Name="mammal" IsBranch="true" Settings="Spectre.Console.Tests.Data.MammalSettings">
|
||||
<Parameters>
|
||||
<Option Short="n,p" Long="name,pet-name" Value="VALUE" Required="false" Kind="scalar" ClrType="System.String" />
|
||||
</Parameters>
|
||||
<!--DOG-->
|
||||
<Command Name="dog" IsBranch="false" ClrType="Spectre.Console.Tests.Data.DogCommand" Settings="Spectre.Console.Tests.Data.DogSettings">
|
||||
<Parameters>
|
||||
<Argument Name="AGE" Position="0" Required="true" Kind="scalar" ClrType="System.Int32" />
|
||||
<Option Short="g" Long="good-boy" Value="NULL" Required="false" Kind="flag" ClrType="System.Boolean" />
|
||||
</Parameters>
|
||||
</Command>
|
||||
<!--HORSE-->
|
||||
<Command Name="horse" IsBranch="false" ClrType="Spectre.Console.Tests.Data.HorseCommand" Settings="Spectre.Console.Tests.Data.MammalSettings">
|
||||
<Parameters>
|
||||
<Option Shadowed="true" Short="n,p" Long="name,pet-name" Value="VALUE" Required="false" Kind="scalar" ClrType="System.String" />
|
||||
</Parameters>
|
||||
</Command>
|
||||
</Command>
|
||||
</Command>
|
||||
</Model>
|
@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Model>
|
||||
<!--DOG-->
|
||||
<Command Name="dog" IsBranch="false" ClrType="Spectre.Console.Tests.Data.DogCommand" Settings="Spectre.Console.Tests.Data.DogSettings">
|
||||
<Parameters>
|
||||
<Argument Name="LEGS" Position="0" Required="false" Kind="scalar" ClrType="System.Int32">
|
||||
<Description>The number of legs.</Description>
|
||||
<Validators>
|
||||
<Validator ClrType="Spectre.Console.Tests.Data.EvenNumberValidatorAttribute" Message="Animals must have an even number of legs." />
|
||||
<Validator ClrType="Spectre.Console.Tests.Data.PositiveNumberValidatorAttribute" Message="Number of legs must be greater than 0." />
|
||||
</Validators>
|
||||
</Argument>
|
||||
<Argument Name="AGE" Position="1" Required="true" Kind="scalar" ClrType="System.Int32" />
|
||||
<Option Short="a" Long="alive,not-dead" Value="NULL" Required="false" Kind="flag" ClrType="System.Boolean">
|
||||
<Description>Indicates whether or not the animal is alive.</Description>
|
||||
</Option>
|
||||
<Option Short="g" Long="good-boy" Value="NULL" Required="false" Kind="flag" ClrType="System.Boolean" />
|
||||
<Option Short="n,p" Long="name,pet-name" Value="VALUE" Required="false" Kind="scalar" ClrType="System.String" />
|
||||
</Parameters>
|
||||
</Command>
|
||||
</Model>
|
@ -0,0 +1,32 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Model>
|
||||
<!--ANIMAL-->
|
||||
<Command Name="animal" IsBranch="true" Settings="Spectre.Console.Tests.Data.AnimalSettings">
|
||||
<Parameters>
|
||||
<Argument Name="LEGS" Position="0" Required="false" Kind="scalar" ClrType="System.Int32">
|
||||
<Description>The number of legs.</Description>
|
||||
<Validators>
|
||||
<Validator ClrType="Spectre.Console.Tests.Data.EvenNumberValidatorAttribute" Message="Animals must have an even number of legs." />
|
||||
<Validator ClrType="Spectre.Console.Tests.Data.PositiveNumberValidatorAttribute" Message="Number of legs must be greater than 0." />
|
||||
</Validators>
|
||||
</Argument>
|
||||
<Option Short="a" Long="alive,not-dead" Value="NULL" Required="false" Kind="flag" ClrType="System.Boolean">
|
||||
<Description>Indicates whether or not the animal is alive.</Description>
|
||||
</Option>
|
||||
</Parameters>
|
||||
<!--DOG-->
|
||||
<Command Name="dog" IsBranch="false" ClrType="Spectre.Console.Tests.Data.DogCommand" Settings="Spectre.Console.Tests.Data.DogSettings">
|
||||
<Parameters>
|
||||
<Argument Name="AGE" Position="0" Required="true" Kind="scalar" ClrType="System.Int32" />
|
||||
<Option Short="g" Long="good-boy" Value="NULL" Required="false" Kind="flag" ClrType="System.Boolean" />
|
||||
<Option Short="n,p" Long="name,pet-name" Value="VALUE" Required="false" Kind="scalar" ClrType="System.String" />
|
||||
</Parameters>
|
||||
</Command>
|
||||
<!--HORSE-->
|
||||
<Command Name="horse" IsBranch="false" ClrType="Spectre.Console.Tests.Data.HorseCommand" Settings="Spectre.Console.Tests.Data.MammalSettings">
|
||||
<Parameters>
|
||||
<Option Short="n,p" Long="name,pet-name" Value="VALUE" Required="false" Kind="scalar" ClrType="System.String" />
|
||||
</Parameters>
|
||||
</Command>
|
||||
</Command>
|
||||
</Model>
|
@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Model>
|
||||
<!--ANIMAL-->
|
||||
<Command Name="animal" IsBranch="true" Settings="Spectre.Console.Tests.Data.AnimalSettings">
|
||||
<Parameters>
|
||||
<Argument Name="LEGS" Position="0" Required="false" Kind="scalar" ClrType="System.Int32">
|
||||
<Description>The number of legs.</Description>
|
||||
<Validators>
|
||||
<Validator ClrType="Spectre.Console.Tests.Data.EvenNumberValidatorAttribute" Message="Animals must have an even number of legs." />
|
||||
<Validator ClrType="Spectre.Console.Tests.Data.PositiveNumberValidatorAttribute" Message="Number of legs must be greater than 0." />
|
||||
</Validators>
|
||||
</Argument>
|
||||
<Option Short="a" Long="alive,not-dead" Value="NULL" Required="false" Kind="flag" ClrType="System.Boolean">
|
||||
<Description>Indicates whether or not the animal is alive.</Description>
|
||||
</Option>
|
||||
</Parameters>
|
||||
<!--DOG-->
|
||||
<Command Name="dog" IsBranch="false" ClrType="Spectre.Console.Tests.Data.DogCommand" Settings="Spectre.Console.Tests.Data.DogSettings">
|
||||
<Parameters>
|
||||
<Argument Name="AGE" Position="0" Required="true" Kind="scalar" ClrType="System.Int32" />
|
||||
<Option Short="g" Long="good-boy" Value="NULL" Required="false" Kind="flag" ClrType="System.Boolean" />
|
||||
<Option Short="n,p" Long="name,pet-name" Value="VALUE" Required="false" Kind="scalar" ClrType="System.String" />
|
||||
</Parameters>
|
||||
</Command>
|
||||
</Command>
|
||||
</Model>
|
@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Model>
|
||||
<!--CMD-->
|
||||
<Command Name="cmd" IsBranch="false" ClrType="Spectre.Console.Tests.Data.OptionVectorCommand" Settings="Spectre.Console.Tests.Data.OptionVectorSettings">
|
||||
<Parameters>
|
||||
<Option Short="" Long="bar" Value="NULL" Required="false" Kind="vector" ClrType="System.Int32[]" />
|
||||
<Option Short="" Long="foo" Value="NULL" Required="false" Kind="vector" ClrType="System.String[]" />
|
||||
</Parameters>
|
||||
</Command>
|
||||
</Model>
|
@ -0,0 +1,37 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Model>
|
||||
<!--DEFAULT COMMAND-->
|
||||
<Command Name="__default_command" IsBranch="false" IsDefault="true" ClrType="Spectre.Console.Tests.Data.DogCommand" Settings="Spectre.Console.Tests.Data.DogSettings">
|
||||
<Parameters>
|
||||
<Argument Name="LEGS" Position="0" Required="false" Kind="scalar" ClrType="System.Int32">
|
||||
<Description>The number of legs.</Description>
|
||||
<Validators>
|
||||
<Validator ClrType="Spectre.Console.Tests.Data.EvenNumberValidatorAttribute" Message="Animals must have an even number of legs." />
|
||||
<Validator ClrType="Spectre.Console.Tests.Data.PositiveNumberValidatorAttribute" Message="Number of legs must be greater than 0." />
|
||||
</Validators>
|
||||
</Argument>
|
||||
<Argument Name="AGE" Position="1" Required="true" Kind="scalar" ClrType="System.Int32" />
|
||||
<Option Short="a" Long="alive,not-dead" Value="NULL" Required="false" Kind="flag" ClrType="System.Boolean">
|
||||
<Description>Indicates whether or not the animal is alive.</Description>
|
||||
</Option>
|
||||
<Option Short="g" Long="good-boy" Value="NULL" Required="false" Kind="flag" ClrType="System.Boolean" />
|
||||
<Option Short="n,p" Long="name,pet-name" Value="VALUE" Required="false" Kind="scalar" ClrType="System.String" />
|
||||
</Parameters>
|
||||
</Command>
|
||||
<!--HORSE-->
|
||||
<Command Name="horse" IsBranch="false" ClrType="Spectre.Console.Tests.Data.HorseCommand" Settings="Spectre.Console.Tests.Data.MammalSettings">
|
||||
<Parameters>
|
||||
<Argument Name="LEGS" Position="0" Required="false" Kind="scalar" ClrType="System.Int32">
|
||||
<Description>The number of legs.</Description>
|
||||
<Validators>
|
||||
<Validator ClrType="Spectre.Console.Tests.Data.EvenNumberValidatorAttribute" Message="Animals must have an even number of legs." />
|
||||
<Validator ClrType="Spectre.Console.Tests.Data.PositiveNumberValidatorAttribute" Message="Number of legs must be greater than 0." />
|
||||
</Validators>
|
||||
</Argument>
|
||||
<Option Short="a" Long="alive,not-dead" Value="NULL" Required="false" Kind="flag" ClrType="System.Boolean">
|
||||
<Description>Indicates whether or not the animal is alive.</Description>
|
||||
</Option>
|
||||
<Option Short="n,p" Long="name,pet-name" Value="VALUE" Required="false" Kind="scalar" ClrType="System.String" />
|
||||
</Parameters>
|
||||
</Command>
|
||||
</Model>
|
@ -0,0 +1,5 @@
|
||||
Error: An error occured when parsing template.
|
||||
Arguments can not contain options.
|
||||
|
||||
--foo <BAR>
|
||||
^^^^^ Not permitted
|
@ -0,0 +1,5 @@
|
||||
Error: An error occured when parsing template.
|
||||
Multiple values are not supported.
|
||||
|
||||
<FOO> <BAR>
|
||||
^^^^^ Too many values
|
@ -0,0 +1,5 @@
|
||||
Error: An error occured when parsing template.
|
||||
Values without name are not allowed.
|
||||
|
||||
<>
|
||||
^^ Missing value name
|
@ -0,0 +1,5 @@
|
||||
Error: An error occured when parsing template.
|
||||
Encountered invalid character '$' in option name.
|
||||
|
||||
--f$oo
|
||||
^ Invalid character
|
@ -0,0 +1,5 @@
|
||||
Error: An error occured when parsing template.
|
||||
Encountered invalid character '$' in value name.
|
||||
|
||||
-f|--foo <F$OO>
|
||||
^ Invalid character
|
@ -0,0 +1,5 @@
|
||||
Error: An error occured when parsing template.
|
||||
Long option names must consist of more than one character.
|
||||
|
||||
--f
|
||||
^ Invalid option name
|
@ -0,0 +1,5 @@
|
||||
Error: An error occured when parsing template.
|
||||
No long or short name for option has been specified.
|
||||
|
||||
<FOO>
|
||||
^^^^^ Missing option. Was this meant to be an argument?
|
@ -0,0 +1,5 @@
|
||||
Error: An error occured when parsing template.
|
||||
Multiple option values are not supported.
|
||||
|
||||
-f|--foo <FOO> <BAR>
|
||||
^^^^^ Too many option values
|
@ -0,0 +1,5 @@
|
||||
Error: An error occured when parsing template.
|
||||
Option names cannot start with a digit.
|
||||
|
||||
--1foo
|
||||
^^^^ Invalid option name
|
@ -0,0 +1,5 @@
|
||||
Error: An error occured when parsing template.
|
||||
Options without name are not allowed.
|
||||
|
||||
--foo|-
|
||||
^ Missing option name
|
@ -0,0 +1,5 @@
|
||||
Error: An error occured when parsing template.
|
||||
Short option names can not be longer than one character.
|
||||
|
||||
--foo|-bar
|
||||
^^^ Invalid option name
|
@ -0,0 +1,5 @@
|
||||
Error: An error occured when parsing template.
|
||||
Encountered unexpected character '$'.
|
||||
|
||||
<FOO> $ <BAR>
|
||||
^ Unexpected character
|
@ -0,0 +1,5 @@
|
||||
Error: An error occured when parsing template.
|
||||
Encountered unterminated value name 'BAR'.
|
||||
|
||||
--foo|-f <BAR
|
||||
^^^^ Unterminated value name
|
@ -1,34 +0,0 @@
|
||||
using System;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace Spectre.Console.Tests
|
||||
{
|
||||
public static class StringExtensions
|
||||
{
|
||||
private static readonly Regex _lineNumberRegex = new Regex(":\\d+", RegexOptions.Singleline);
|
||||
private static readonly Regex _filenameRegex = new Regex("\\sin\\s.*cs:nn", RegexOptions.Multiline);
|
||||
|
||||
public static string NormalizeLineEndings(this string text)
|
||||
{
|
||||
return text?.Replace("\r\n", "\n", StringComparison.OrdinalIgnoreCase)
|
||||
?.Replace("\r", string.Empty, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
public static string NormalizeStackTrace(this string text)
|
||||
{
|
||||
text = _lineNumberRegex.Replace(text, match =>
|
||||
{
|
||||
return ":nn";
|
||||
});
|
||||
|
||||
return _filenameRegex.Replace(text, match =>
|
||||
{
|
||||
var value = match.Value;
|
||||
var index = value.LastIndexOfAny(new[] { '\\', '/' });
|
||||
var filename = value.Substring(index + 1, value.Length - index - 1);
|
||||
|
||||
return $" in /xyz/{filename}";
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
@ -1,15 +0,0 @@
|
||||
namespace Spectre.Console.Tests
|
||||
{
|
||||
internal static class StyleExtensions
|
||||
{
|
||||
public static Style SetColor(this Style style, Color color, bool foreground)
|
||||
{
|
||||
if (foreground)
|
||||
{
|
||||
return style.Foreground(color);
|
||||
}
|
||||
|
||||
return style.Background(color);
|
||||
}
|
||||
}
|
||||
}
|
@ -2,9 +2,12 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net5.0</TargetFrameworks>
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="..\Spectre.Console\Cli\Internal\Constants.cs" Link="Imported\Constants.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Remove="Data\starwars.flf" />
|
||||
</ItemGroup>
|
||||
@ -25,6 +28,7 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Spectre.Console.Testing\Spectre.Console.Testing.csproj" />
|
||||
<ProjectReference Include="..\Spectre.Console\Spectre.Console.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
|
@ -1,17 +0,0 @@
|
||||
namespace Spectre.Console.Tests
|
||||
{
|
||||
public sealed class DummyCursor : IAnsiConsoleCursor
|
||||
{
|
||||
public void Move(CursorDirection direction, int steps)
|
||||
{
|
||||
}
|
||||
|
||||
public void SetPosition(int column, int line)
|
||||
{
|
||||
}
|
||||
|
||||
public void Show(bool show)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Spectre.Console.Tests
|
||||
{
|
||||
public sealed class DummySpinner1 : Spinner
|
||||
{
|
||||
public override TimeSpan Interval => TimeSpan.FromMilliseconds(100);
|
||||
public override bool IsUnicode => true;
|
||||
public override IReadOnlyList<string> Frames => new List<string>
|
||||
{
|
||||
"*",
|
||||
};
|
||||
}
|
||||
|
||||
public sealed class DummySpinner2 : Spinner
|
||||
{
|
||||
public override TimeSpan Interval => TimeSpan.FromMilliseconds(100);
|
||||
public override bool IsUnicode => true;
|
||||
public override IReadOnlyList<string> Frames => new List<string>
|
||||
{
|
||||
"-",
|
||||
};
|
||||
}
|
||||
}
|
@ -1,77 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Spectre.Console.Rendering;
|
||||
|
||||
namespace Spectre.Console.Tests
|
||||
{
|
||||
public sealed class PlainConsole : IAnsiConsole, IDisposable
|
||||
{
|
||||
public Capabilities Capabilities { get; }
|
||||
public Encoding Encoding { get; }
|
||||
public IAnsiConsoleCursor Cursor => new DummyCursor();
|
||||
public TestableConsoleInput Input { get; }
|
||||
|
||||
public int Width { get; }
|
||||
public int Height { get; }
|
||||
|
||||
IAnsiConsoleInput IAnsiConsole.Input => Input;
|
||||
public RenderPipeline Pipeline { get; }
|
||||
|
||||
public Decoration Decoration { get; set; }
|
||||
public Color Foreground { get; set; }
|
||||
public Color Background { get; set; }
|
||||
public string Link { get; set; }
|
||||
|
||||
public StringWriter Writer { get; }
|
||||
public string Output => Writer.ToString();
|
||||
public IReadOnlyList<string> Lines => Output.TrimEnd('\n').Split(new char[] { '\n' });
|
||||
|
||||
public PlainConsole(
|
||||
int width = 80, int height = 9000, Encoding encoding = null,
|
||||
bool supportsAnsi = true, ColorSystem colorSystem = ColorSystem.Standard,
|
||||
bool legacyConsole = false, bool interactive = true)
|
||||
{
|
||||
Capabilities = new Capabilities(supportsAnsi, colorSystem, legacyConsole, interactive);
|
||||
Encoding = encoding ?? Encoding.UTF8;
|
||||
Width = width;
|
||||
Height = height;
|
||||
Writer = new StringWriter();
|
||||
Input = new TestableConsoleInput();
|
||||
Pipeline = new RenderPipeline();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Writer.Dispose();
|
||||
}
|
||||
|
||||
public void Clear(bool home)
|
||||
{
|
||||
}
|
||||
|
||||
public void Write(IEnumerable<Segment> segments)
|
||||
{
|
||||
if (segments is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var segment in segments)
|
||||
{
|
||||
Writer.Write(segment.Text);
|
||||
}
|
||||
}
|
||||
|
||||
public string WriteNormalizedException(Exception ex, ExceptionFormats formats = ExceptionFormats.Default)
|
||||
{
|
||||
this.WriteException(ex, formats);
|
||||
return string.Join("\n", Output.NormalizeStackTrace()
|
||||
.NormalizeLineEndings()
|
||||
.Split(new char[] { '\n' })
|
||||
.Select(line => line.TrimEnd()));
|
||||
}
|
||||
}
|
||||
}
|
@ -1,21 +0,0 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace Spectre.Console.Tests
|
||||
{
|
||||
public static class ResourceReader
|
||||
{
|
||||
public static Stream LoadResourceStream(string resourceName)
|
||||
{
|
||||
if (resourceName is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(resourceName));
|
||||
}
|
||||
|
||||
var assembly = typeof(EmbeddedResourceDataAttribute).Assembly;
|
||||
resourceName = resourceName.Replace("/", ".", StringComparison.Ordinal);
|
||||
|
||||
return assembly.GetManifestResourceStream(resourceName);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
namespace Spectre.Console.Tests
|
||||
{
|
||||
public sealed class TestLinkIdentityGenerator : ILinkIdentityGenerator
|
||||
{
|
||||
public int GenerateId(string link, string text)
|
||||
{
|
||||
return 1024;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,68 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using Spectre.Console.Rendering;
|
||||
|
||||
namespace Spectre.Console.Tests
|
||||
{
|
||||
public sealed class TestableAnsiConsole : IDisposable, IAnsiConsole
|
||||
{
|
||||
private readonly StringWriter _writer;
|
||||
private readonly IAnsiConsole _console;
|
||||
|
||||
public string Output => _writer.ToString();
|
||||
|
||||
public Capabilities Capabilities => _console.Capabilities;
|
||||
public Encoding Encoding => _console.Encoding;
|
||||
public int Width { get; }
|
||||
public int Height => _console.Height;
|
||||
public IAnsiConsoleCursor Cursor => _console.Cursor;
|
||||
public TestableConsoleInput Input { get; }
|
||||
public RenderPipeline Pipeline => _console.Pipeline;
|
||||
|
||||
IAnsiConsoleInput IAnsiConsole.Input => Input;
|
||||
|
||||
public TestableAnsiConsole(
|
||||
ColorSystem system, AnsiSupport ansi = AnsiSupport.Yes,
|
||||
InteractionSupport interaction = InteractionSupport.Yes,
|
||||
int width = 80)
|
||||
{
|
||||
_writer = new StringWriter();
|
||||
_console = AnsiConsole.Create(new AnsiConsoleSettings
|
||||
{
|
||||
Ansi = ansi,
|
||||
ColorSystem = (ColorSystemSupport)system,
|
||||
Interactive = interaction,
|
||||
Out = _writer,
|
||||
LinkIdentityGenerator = new TestLinkIdentityGenerator(),
|
||||
});
|
||||
|
||||
Width = width;
|
||||
Input = new TestableConsoleInput();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_writer?.Dispose();
|
||||
}
|
||||
|
||||
public void Clear(bool home)
|
||||
{
|
||||
_console.Clear(home);
|
||||
}
|
||||
|
||||
public void Write(IEnumerable<Segment> segments)
|
||||
{
|
||||
if (segments is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var segment in segments)
|
||||
{
|
||||
_console.Write(segment);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,55 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Spectre.Console.Tests
|
||||
{
|
||||
public sealed class TestableConsoleInput : IAnsiConsoleInput
|
||||
{
|
||||
private readonly Queue<ConsoleKeyInfo> _input;
|
||||
|
||||
public TestableConsoleInput()
|
||||
{
|
||||
_input = new Queue<ConsoleKeyInfo>();
|
||||
}
|
||||
|
||||
public void PushText(string input)
|
||||
{
|
||||
if (input is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(input));
|
||||
}
|
||||
|
||||
foreach (var character in input)
|
||||
{
|
||||
PushCharacter(character);
|
||||
}
|
||||
}
|
||||
|
||||
public void PushTextWithEnter(string input)
|
||||
{
|
||||
PushText(input);
|
||||
PushKey(ConsoleKey.Enter);
|
||||
}
|
||||
|
||||
public void PushCharacter(char character)
|
||||
{
|
||||
var control = char.IsUpper(character);
|
||||
_input.Enqueue(new ConsoleKeyInfo(character, (ConsoleKey)character, false, false, control));
|
||||
}
|
||||
|
||||
public void PushKey(ConsoleKey key)
|
||||
{
|
||||
_input.Enqueue(new ConsoleKeyInfo((char)key, key, false, false, false));
|
||||
}
|
||||
|
||||
public ConsoleKeyInfo ReadKey(bool intercept)
|
||||
{
|
||||
if (_input.Count == 0)
|
||||
{
|
||||
throw new InvalidOperationException("No input available.");
|
||||
}
|
||||
|
||||
return _input.Dequeue();
|
||||
}
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user