mirror of
				https://github.com/nsnail/spectre.console.git
				synced 2025-11-04 18:40:50 +08:00 
			
		
		
		
	Alias for command branches (#411)
This commit is contained in:
		@@ -88,12 +88,12 @@ public static class ConfiguratorExtensions
 | 
			
		||||
 | 
			
		||||
        configurator.Settings.StrictParsing = true;
 | 
			
		||||
        return configurator;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Tells the help writer whether or not to trim trailing period.
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <param name="configurator">The configurator.</param>
 | 
			
		||||
    /// <param name="configurator">The configurator.</param>
 | 
			
		||||
    /// <param name="trimTrailingPeriods">True to trim trailing period (default), false to not.</param>
 | 
			
		||||
    /// <returns>A configurator that can be used to configure the application further.</returns>
 | 
			
		||||
    public static IConfigurator TrimTrailingPeriods(this IConfigurator configurator, bool trimTrailingPeriods)
 | 
			
		||||
@@ -181,7 +181,8 @@ public static class ConfiguratorExtensions
 | 
			
		||||
    /// <param name="configurator">The configurator.</param>
 | 
			
		||||
    /// <param name="name">The name of the command branch.</param>
 | 
			
		||||
    /// <param name="action">The command branch configuration.</param>
 | 
			
		||||
    public static void AddBranch(
 | 
			
		||||
    /// <returns>A branch configurator that can be used to configure the branch further.</returns>
 | 
			
		||||
    public static IBranchConfigurator AddBranch(
 | 
			
		||||
        this IConfigurator configurator,
 | 
			
		||||
        string name,
 | 
			
		||||
        Action<IConfigurator<CommandSettings>> action)
 | 
			
		||||
@@ -191,7 +192,7 @@ public static class ConfiguratorExtensions
 | 
			
		||||
            throw new ArgumentNullException(nameof(configurator));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        configurator.AddBranch(name, action);
 | 
			
		||||
        return configurator.AddBranch(name, action);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
@@ -201,7 +202,8 @@ public static class ConfiguratorExtensions
 | 
			
		||||
    /// <param name="configurator">The configurator.</param>
 | 
			
		||||
    /// <param name="name">The name of the command branch.</param>
 | 
			
		||||
    /// <param name="action">The command branch configuration.</param>
 | 
			
		||||
    public static void AddBranch<TSettings>(
 | 
			
		||||
    /// <returns>A branch configurator that can be used to configure the branch further.</returns>
 | 
			
		||||
    public static IBranchConfigurator AddBranch<TSettings>(
 | 
			
		||||
        this IConfigurator<TSettings> configurator,
 | 
			
		||||
        string name,
 | 
			
		||||
        Action<IConfigurator<TSettings>> action)
 | 
			
		||||
@@ -212,7 +214,7 @@ public static class ConfiguratorExtensions
 | 
			
		||||
            throw new ArgumentNullException(nameof(configurator));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        configurator.AddBranch(name, action);
 | 
			
		||||
        return configurator.AddBranch(name, action);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										14
									
								
								src/Spectre.Console.Cli/IBranchConfigurator.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								src/Spectre.Console.Cli/IBranchConfigurator.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,14 @@
 | 
			
		||||
namespace Spectre.Console.Cli;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
/// Represents a branch configurator.
 | 
			
		||||
/// </summary>
 | 
			
		||||
public interface IBranchConfigurator
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Adds an alias (an alternative name) to the branch being configured.
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <param name="name">The alias to add to the branch being configured.</param>
 | 
			
		||||
    /// <returns>The same <see cref="IBranchConfigurator"/> instance so that multiple calls can be chained.</returns>
 | 
			
		||||
    IBranchConfigurator WithAlias(string name);
 | 
			
		||||
}
 | 
			
		||||
@@ -41,6 +41,7 @@ public interface IConfigurator
 | 
			
		||||
    /// <typeparam name="TSettings">The command setting type.</typeparam>
 | 
			
		||||
    /// <param name="name">The name of the command branch.</param>
 | 
			
		||||
    /// <param name="action">The command branch configurator.</param>
 | 
			
		||||
    void AddBranch<TSettings>(string name, Action<IConfigurator<TSettings>> action)
 | 
			
		||||
    /// <returns>A branch configurator that can be used to configure the branch further.</returns>
 | 
			
		||||
    IBranchConfigurator AddBranch<TSettings>(string name, Action<IConfigurator<TSettings>> action)
 | 
			
		||||
        where TSettings : CommandSettings;
 | 
			
		||||
}
 | 
			
		||||
@@ -51,6 +51,7 @@ public interface IConfigurator<in TSettings>
 | 
			
		||||
    /// <typeparam name="TDerivedSettings">The derived command setting type.</typeparam>
 | 
			
		||||
    /// <param name="name">The name of the command branch.</param>
 | 
			
		||||
    /// <param name="action">The command branch configuration.</param>
 | 
			
		||||
    void AddBranch<TDerivedSettings>(string name, Action<IConfigurator<TDerivedSettings>> action)
 | 
			
		||||
    /// <returns>A branch configurator that can be used to configure the branch further.</returns>
 | 
			
		||||
    IBranchConfigurator AddBranch<TDerivedSettings>(string name, Action<IConfigurator<TDerivedSettings>> action)
 | 
			
		||||
        where TDerivedSettings : TSettings;
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,17 @@
 | 
			
		||||
namespace Spectre.Console.Cli;
 | 
			
		||||
 | 
			
		||||
internal sealed class BranchConfigurator : IBranchConfigurator
 | 
			
		||||
{
 | 
			
		||||
    public ConfiguredCommand Command { get; }
 | 
			
		||||
 | 
			
		||||
    public BranchConfigurator(ConfiguredCommand command)
 | 
			
		||||
    {
 | 
			
		||||
        Command = command;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public IBranchConfigurator WithAlias(string alias)
 | 
			
		||||
    {
 | 
			
		||||
        Command.Aliases.Add(alias);
 | 
			
		||||
        return this;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -48,12 +48,13 @@ internal sealed class Configurator : IUnsafeConfigurator, IConfigurator, IConfig
 | 
			
		||||
        return new CommandConfigurator(command);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void AddBranch<TSettings>(string name, Action<IConfigurator<TSettings>> action)
 | 
			
		||||
    public IBranchConfigurator AddBranch<TSettings>(string name, Action<IConfigurator<TSettings>> action)
 | 
			
		||||
        where TSettings : CommandSettings
 | 
			
		||||
    {
 | 
			
		||||
        var command = ConfiguredCommand.FromBranch<TSettings>(name);
 | 
			
		||||
        action(new Configurator<TSettings>(command, _registrar));
 | 
			
		||||
        Commands.Add(command);
 | 
			
		||||
        var added = Commands.AddAndReturn(command);
 | 
			
		||||
        return new BranchConfigurator(added);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ICommandConfigurator IUnsafeConfigurator.AddCommand(string name, Type command)
 | 
			
		||||
@@ -74,7 +75,7 @@ internal sealed class Configurator : IUnsafeConfigurator, IConfigurator, IConfig
 | 
			
		||||
        return result;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void IUnsafeConfigurator.AddBranch(string name, Type settings, Action<IUnsafeBranchConfigurator> action)
 | 
			
		||||
    IBranchConfigurator IUnsafeConfigurator.AddBranch(string name, Type settings, Action<IUnsafeBranchConfigurator> action)
 | 
			
		||||
    {
 | 
			
		||||
        var command = ConfiguredCommand.FromBranch(settings, name);
 | 
			
		||||
 | 
			
		||||
@@ -86,6 +87,7 @@ internal sealed class Configurator : IUnsafeConfigurator, IConfigurator, IConfig
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        action(configurator);
 | 
			
		||||
        Commands.Add(command);
 | 
			
		||||
        var added = Commands.AddAndReturn(command);
 | 
			
		||||
        return new BranchConfigurator(added);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -47,12 +47,13 @@ internal sealed class Configurator<TSettings> : IUnsafeBranchConfigurator, IConf
 | 
			
		||||
        return new CommandConfigurator(command);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void AddBranch<TDerivedSettings>(string name, Action<IConfigurator<TDerivedSettings>> action)
 | 
			
		||||
    public IBranchConfigurator AddBranch<TDerivedSettings>(string name, Action<IConfigurator<TDerivedSettings>> action)
 | 
			
		||||
        where TDerivedSettings : TSettings
 | 
			
		||||
    {
 | 
			
		||||
        var command = ConfiguredCommand.FromBranch<TDerivedSettings>(name);
 | 
			
		||||
        action(new Configurator<TDerivedSettings>(command, _registrar));
 | 
			
		||||
        _command.Children.Add(command);
 | 
			
		||||
        var added = _command.Children.AddAndReturn(command);
 | 
			
		||||
        return new BranchConfigurator(added);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ICommandConfigurator IUnsafeConfigurator.AddCommand(string name, Type command)
 | 
			
		||||
@@ -73,7 +74,7 @@ internal sealed class Configurator<TSettings> : IUnsafeBranchConfigurator, IConf
 | 
			
		||||
        return result;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void IUnsafeConfigurator.AddBranch(string name, Type settings, Action<IUnsafeBranchConfigurator> action)
 | 
			
		||||
    IBranchConfigurator IUnsafeConfigurator.AddBranch(string name, Type settings, Action<IUnsafeBranchConfigurator> action)
 | 
			
		||||
    {
 | 
			
		||||
        var command = ConfiguredCommand.FromBranch(settings, name);
 | 
			
		||||
 | 
			
		||||
@@ -85,6 +86,7 @@ internal sealed class Configurator<TSettings> : IUnsafeBranchConfigurator, IConf
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        action(configurator);
 | 
			
		||||
        _command.Children.Add(command);
 | 
			
		||||
        var added = _command.Children.AddAndReturn(command);
 | 
			
		||||
        return new BranchConfigurator(added);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -19,5 +19,6 @@ public interface IUnsafeConfigurator
 | 
			
		||||
    /// <param name="name">The name of the command branch.</param>
 | 
			
		||||
    /// <param name="settings">The command setting type.</param>
 | 
			
		||||
    /// <param name="action">The command branch configurator.</param>
 | 
			
		||||
    void AddBranch(string name, Type settings, Action<IUnsafeBranchConfigurator> action);
 | 
			
		||||
    /// <returns>A branch configurator that can be used to configure the branch further.</returns>
 | 
			
		||||
    IBranchConfigurator AddBranch(string name, Type settings, Action<IUnsafeBranchConfigurator> action);
 | 
			
		||||
}
 | 
			
		||||
@@ -132,8 +132,8 @@ public sealed partial class CommandAppTests
 | 
			
		||||
            dog.IsAlive.ShouldBe(false);
 | 
			
		||||
            dog.Name.ShouldBe("Rufus");
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    [Fact]
 | 
			
		||||
    public void Should_Pass_Case_5()
 | 
			
		||||
    {
 | 
			
		||||
@@ -165,7 +165,7 @@ public sealed partial class CommandAppTests
 | 
			
		||||
            dog.IsAlive.ShouldBe(true);
 | 
			
		||||
            dog.Name.ShouldBe("Rufus");
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    [Fact]
 | 
			
		||||
    public void Should_Pass_Case_6()
 | 
			
		||||
@@ -237,10 +237,10 @@ public sealed partial class CommandAppTests
 | 
			
		||||
        var result = app.Run(new[]
 | 
			
		||||
        {
 | 
			
		||||
            "dog", "12", "4",
 | 
			
		||||
            "--name=\" -Rufus --' ",
 | 
			
		||||
            "--",
 | 
			
		||||
            "--order-by", "\"-size\"",
 | 
			
		||||
            "--order-by", " ",
 | 
			
		||||
            "--name=\" -Rufus --' ",
 | 
			
		||||
            "--",
 | 
			
		||||
            "--order-by", "\"-size\"",
 | 
			
		||||
            "--order-by", " ",
 | 
			
		||||
            "--order-by", string.Empty,
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
@@ -249,8 +249,8 @@ public sealed partial class CommandAppTests
 | 
			
		||||
        result.Settings.ShouldBeOfType<DogSettings>().And(dog =>
 | 
			
		||||
        {
 | 
			
		||||
            dog.Name.ShouldBe("\" -Rufus --' ");
 | 
			
		||||
        });
 | 
			
		||||
        result.Context.Remaining.Parsed.Count.ShouldBe(1);
 | 
			
		||||
        });
 | 
			
		||||
        result.Context.Remaining.Parsed.Count.ShouldBe(1);
 | 
			
		||||
        result.Context.ShouldHaveRemainingArgument("order-by", values: new[] { "\"-size\"", " ", string.Empty });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -280,6 +280,65 @@ public sealed partial class CommandAppTests
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    [Fact]
 | 
			
		||||
    public void Should_Be_Able_To_Use_Branch_Alias()
 | 
			
		||||
    {
 | 
			
		||||
        // Given
 | 
			
		||||
        var app = new CommandAppTester();
 | 
			
		||||
        app.Configure(config =>
 | 
			
		||||
        {
 | 
			
		||||
            config.PropagateExceptions();
 | 
			
		||||
            config.AddBranch<AnimalSettings>("animal", animal =>
 | 
			
		||||
            {
 | 
			
		||||
                animal.AddCommand<DogCommand>("dog");
 | 
			
		||||
                animal.AddCommand<HorseCommand>("horse");
 | 
			
		||||
            }).WithAlias("a");
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        // When
 | 
			
		||||
        var result = app.Run(new[]
 | 
			
		||||
        {
 | 
			
		||||
            "a", "dog", "12", "--good-boy",
 | 
			
		||||
            "--name", "Rufus",
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        // Then
 | 
			
		||||
        result.ExitCode.ShouldBe(0);
 | 
			
		||||
        result.Settings.ShouldBeOfType<DogSettings>().And(dog =>
 | 
			
		||||
        {
 | 
			
		||||
            dog.Age.ShouldBe(12);
 | 
			
		||||
            dog.GoodBoy.ShouldBe(true);
 | 
			
		||||
            dog.Name.ShouldBe("Rufus");
 | 
			
		||||
            dog.IsAlive.ShouldBe(false);
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    [Fact]
 | 
			
		||||
    public void Should_Throw_If_Branch_Alias_Conflicts_With_Another_Command()
 | 
			
		||||
    {
 | 
			
		||||
        // Given
 | 
			
		||||
        var app = new CommandApp();
 | 
			
		||||
        app.Configure(config =>
 | 
			
		||||
        {
 | 
			
		||||
            config.PropagateExceptions();
 | 
			
		||||
            config.AddCommand<DogCommand>("a");
 | 
			
		||||
            config.AddBranch<AnimalSettings>("animal", animal =>
 | 
			
		||||
            {
 | 
			
		||||
                animal.AddCommand<DogCommand>("dog");
 | 
			
		||||
                animal.AddCommand<HorseCommand>("horse");
 | 
			
		||||
            }).WithAlias("a");
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        // When
 | 
			
		||||
        var result = Record.Exception(() => app.Run(new[] { "a", "0", "12" }));
 | 
			
		||||
 | 
			
		||||
        // Then
 | 
			
		||||
        result.ShouldBeOfType<CommandConfigurationException>().And(ex =>
 | 
			
		||||
        {
 | 
			
		||||
            ex.Message.ShouldBe("The alias 'a' for 'animal' conflicts with another command.");
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    [Fact]
 | 
			
		||||
    public void Should_Assign_Default_Value_To_Optional_Argument()
 | 
			
		||||
    {
 | 
			
		||||
@@ -554,181 +613,181 @@ public sealed partial class CommandAppTests
 | 
			
		||||
        {
 | 
			
		||||
            dog.IsAlive.ShouldBe(expected);
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    [Fact]
 | 
			
		||||
    public void Should_Set_Short_Option_Before_Argument()
 | 
			
		||||
    {
 | 
			
		||||
        // Given
 | 
			
		||||
        var app = new CommandAppTester();
 | 
			
		||||
        app.Configure(config =>
 | 
			
		||||
        {
 | 
			
		||||
            config.PropagateExceptions();
 | 
			
		||||
            config.AddCommand<DogCommand>("dog");
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        // When
 | 
			
		||||
        var result = app.Run(new[] { "dog", "-a", "-n=Rufus", "4", "12", });
 | 
			
		||||
 | 
			
		||||
        // Then
 | 
			
		||||
        result.ExitCode.ShouldBe(0);
 | 
			
		||||
        result.Settings.ShouldBeOfType<DogSettings>().And(settings =>
 | 
			
		||||
        {
 | 
			
		||||
            settings.IsAlive.ShouldBeTrue();
 | 
			
		||||
            settings.Name.ShouldBe("Rufus");
 | 
			
		||||
            settings.Legs.ShouldBe(4);
 | 
			
		||||
            settings.Age.ShouldBe(12);
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    [Fact]
 | 
			
		||||
    public void Should_Set_Short_Option_Before_Argument()
 | 
			
		||||
    {
 | 
			
		||||
        // Given
 | 
			
		||||
        var app = new CommandAppTester();
 | 
			
		||||
        app.Configure(config =>
 | 
			
		||||
        {
 | 
			
		||||
            config.PropagateExceptions();
 | 
			
		||||
            config.AddCommand<DogCommand>("dog");
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        // When
 | 
			
		||||
        var result = app.Run(new[] { "dog", "-a", "-n=Rufus", "4", "12", });
 | 
			
		||||
 | 
			
		||||
        // Then
 | 
			
		||||
        result.ExitCode.ShouldBe(0);
 | 
			
		||||
        result.Settings.ShouldBeOfType<DogSettings>().And(settings =>
 | 
			
		||||
        {
 | 
			
		||||
            settings.IsAlive.ShouldBeTrue();
 | 
			
		||||
            settings.Name.ShouldBe("Rufus");
 | 
			
		||||
            settings.Legs.ShouldBe(4);
 | 
			
		||||
            settings.Age.ShouldBe(12);
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    [Theory]
 | 
			
		||||
    [InlineData("true", true)]
 | 
			
		||||
    [InlineData("True", true)]
 | 
			
		||||
    [InlineData("false", false)]
 | 
			
		||||
    [InlineData("False", false)]
 | 
			
		||||
    public void Should_Set_Short_Option_With_Explicit_Boolan_Flag_Before_Argument(string value, bool expected)
 | 
			
		||||
    {
 | 
			
		||||
        // Given
 | 
			
		||||
        var app = new CommandAppTester();
 | 
			
		||||
        app.Configure(config =>
 | 
			
		||||
        {
 | 
			
		||||
            config.PropagateExceptions();
 | 
			
		||||
            config.AddCommand<DogCommand>("dog");
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        // When
 | 
			
		||||
        var result = app.Run(new[] { "dog", "-a", value, "4", "12", });
 | 
			
		||||
 | 
			
		||||
        // Then
 | 
			
		||||
        result.ExitCode.ShouldBe(0);
 | 
			
		||||
        result.Settings.ShouldBeOfType<DogSettings>().And(settings =>
 | 
			
		||||
        {
 | 
			
		||||
            settings.IsAlive.ShouldBe(expected);
 | 
			
		||||
            settings.Legs.ShouldBe(4);
 | 
			
		||||
            settings.Age.ShouldBe(12);
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    [Fact]
 | 
			
		||||
    public void Should_Set_Long_Option_Before_Argument()
 | 
			
		||||
    {
 | 
			
		||||
        // Given
 | 
			
		||||
        var app = new CommandAppTester();
 | 
			
		||||
        app.Configure(config =>
 | 
			
		||||
        {
 | 
			
		||||
            config.PropagateExceptions();
 | 
			
		||||
            config.AddCommand<DogCommand>("dog");
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        // When
 | 
			
		||||
        var result = app.Run(new[] { "dog", "--alive", "--name=Rufus", "4", "12" });
 | 
			
		||||
 | 
			
		||||
        // Then
 | 
			
		||||
        result.ExitCode.ShouldBe(0);
 | 
			
		||||
        result.Settings.ShouldBeOfType<DogSettings>().And(settings =>
 | 
			
		||||
        {
 | 
			
		||||
            settings.IsAlive.ShouldBeTrue();
 | 
			
		||||
            settings.Name.ShouldBe("Rufus");
 | 
			
		||||
            settings.Legs.ShouldBe(4);
 | 
			
		||||
            settings.Age.ShouldBe(12);
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    [InlineData("False", false)]
 | 
			
		||||
    public void Should_Set_Short_Option_With_Explicit_Boolan_Flag_Before_Argument(string value, bool expected)
 | 
			
		||||
    {
 | 
			
		||||
        // Given
 | 
			
		||||
        var app = new CommandAppTester();
 | 
			
		||||
        app.Configure(config =>
 | 
			
		||||
        {
 | 
			
		||||
            config.PropagateExceptions();
 | 
			
		||||
            config.AddCommand<DogCommand>("dog");
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        // When
 | 
			
		||||
        var result = app.Run(new[] { "dog", "-a", value, "4", "12", });
 | 
			
		||||
 | 
			
		||||
        // Then
 | 
			
		||||
        result.ExitCode.ShouldBe(0);
 | 
			
		||||
        result.Settings.ShouldBeOfType<DogSettings>().And(settings =>
 | 
			
		||||
        {
 | 
			
		||||
            settings.IsAlive.ShouldBe(expected);
 | 
			
		||||
            settings.Legs.ShouldBe(4);
 | 
			
		||||
            settings.Age.ShouldBe(12);
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    [Fact]
 | 
			
		||||
    public void Should_Set_Long_Option_Before_Argument()
 | 
			
		||||
    {
 | 
			
		||||
        // Given
 | 
			
		||||
        var app = new CommandAppTester();
 | 
			
		||||
        app.Configure(config =>
 | 
			
		||||
        {
 | 
			
		||||
            config.PropagateExceptions();
 | 
			
		||||
            config.AddCommand<DogCommand>("dog");
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        // When
 | 
			
		||||
        var result = app.Run(new[] { "dog", "--alive", "--name=Rufus", "4", "12" });
 | 
			
		||||
 | 
			
		||||
        // Then
 | 
			
		||||
        result.ExitCode.ShouldBe(0);
 | 
			
		||||
        result.Settings.ShouldBeOfType<DogSettings>().And(settings =>
 | 
			
		||||
        {
 | 
			
		||||
            settings.IsAlive.ShouldBeTrue();
 | 
			
		||||
            settings.Name.ShouldBe("Rufus");
 | 
			
		||||
            settings.Legs.ShouldBe(4);
 | 
			
		||||
            settings.Age.ShouldBe(12);
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    [Theory]
 | 
			
		||||
    [InlineData("true", true)]
 | 
			
		||||
    [InlineData("True", true)]
 | 
			
		||||
    [InlineData("false", false)]
 | 
			
		||||
    [InlineData("False", false)]
 | 
			
		||||
    public void Should_Set_Long_Option_With_Explicit_Boolan_Flag_Before_Argument(string value, bool expected)
 | 
			
		||||
    {
 | 
			
		||||
        // Given
 | 
			
		||||
        var app = new CommandAppTester();
 | 
			
		||||
        app.Configure(config =>
 | 
			
		||||
        {
 | 
			
		||||
            config.PropagateExceptions();
 | 
			
		||||
            config.AddCommand<DogCommand>("dog");
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        // When
 | 
			
		||||
        var result = app.Run(new[] { "dog", "--alive", value, "4", "12", });
 | 
			
		||||
 | 
			
		||||
        // Then
 | 
			
		||||
        result.ExitCode.ShouldBe(0);
 | 
			
		||||
        result.Settings.ShouldBeOfType<DogSettings>().And(settings =>
 | 
			
		||||
        {
 | 
			
		||||
            settings.IsAlive.ShouldBe(expected);
 | 
			
		||||
            settings.Legs.ShouldBe(4);
 | 
			
		||||
            settings.Age.ShouldBe(12);
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    [Theory]
 | 
			
		||||
 | 
			
		||||
    [InlineData("False", false)]
 | 
			
		||||
    public void Should_Set_Long_Option_With_Explicit_Boolan_Flag_Before_Argument(string value, bool expected)
 | 
			
		||||
    {
 | 
			
		||||
        // Given
 | 
			
		||||
        var app = new CommandAppTester();
 | 
			
		||||
        app.Configure(config =>
 | 
			
		||||
        {
 | 
			
		||||
            config.PropagateExceptions();
 | 
			
		||||
            config.AddCommand<DogCommand>("dog");
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        // When
 | 
			
		||||
        var result = app.Run(new[] { "dog", "--alive", value, "4", "12", });
 | 
			
		||||
 | 
			
		||||
        // Then
 | 
			
		||||
        result.ExitCode.ShouldBe(0);
 | 
			
		||||
        result.Settings.ShouldBeOfType<DogSettings>().And(settings =>
 | 
			
		||||
        {
 | 
			
		||||
            settings.IsAlive.ShouldBe(expected);
 | 
			
		||||
            settings.Legs.ShouldBe(4);
 | 
			
		||||
            settings.Age.ShouldBe(12);
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    [Theory]
 | 
			
		||||
 | 
			
		||||
    // Long options
 | 
			
		||||
    [InlineData("dog --alive 4 12 --name Rufus", 4, 12, false, true, "Rufus")]
 | 
			
		||||
    [InlineData("dog --alive=true 4 12 --name Rufus", 4, 12, false, true, "Rufus")]
 | 
			
		||||
    [InlineData("dog --alive:true 4 12 --name Rufus", 4, 12, false, true, "Rufus")]
 | 
			
		||||
    [InlineData("dog --alive --good-boy 4 12 --name Rufus", 4, 12, true, true, "Rufus")]
 | 
			
		||||
    [InlineData("dog --alive=true --good-boy=true 4 12 --name Rufus", 4, 12, true, true, "Rufus")]
 | 
			
		||||
    [InlineData("dog --alive:true --good-boy:true 4 12 --name Rufus", 4, 12, true, true, "Rufus")]
 | 
			
		||||
    [InlineData("dog --alive --good-boy --name Rufus 4 12", 4, 12, true, true, "Rufus")]
 | 
			
		||||
    [InlineData("dog --alive=true --good-boy=true --name Rufus 4 12", 4, 12, true, true, "Rufus")]
 | 
			
		||||
    [InlineData("dog --alive:true --good-boy:true --name Rufus 4 12", 4, 12, true, true, "Rufus")]
 | 
			
		||||
 | 
			
		||||
    // Short options
 | 
			
		||||
    [InlineData("dog -a 4 12 --name Rufus", 4, 12, false, true, "Rufus")]
 | 
			
		||||
    [InlineData("dog -a=true 4 12 --name Rufus", 4, 12, false, true, "Rufus")]
 | 
			
		||||
    [InlineData("dog -a:true 4 12 --name Rufus", 4, 12, false, true, "Rufus")]
 | 
			
		||||
    [InlineData("dog -a --good-boy 4 12 --name Rufus", 4, 12, true, true, "Rufus")]
 | 
			
		||||
    [InlineData("dog -a=true -g=true 4 12 --name Rufus", 4, 12, true, true, "Rufus")]
 | 
			
		||||
    [InlineData("dog -a:true -g:true 4 12 --name Rufus", 4, 12, true, true, "Rufus")]
 | 
			
		||||
    [InlineData("dog -a -g --name Rufus 4 12", 4, 12, true, true, "Rufus")]
 | 
			
		||||
    [InlineData("dog -a=true -g=true --name Rufus 4 12", 4, 12, true, true, "Rufus")]
 | 
			
		||||
    [InlineData("dog -a:true -g:true --name Rufus 4 12", 4, 12, true, true, "Rufus")]
 | 
			
		||||
 | 
			
		||||
    // Switch around ordering of the options
 | 
			
		||||
    [InlineData("dog --good-boy:true --name Rufus --alive:true 4 12", 4, 12, true, true, "Rufus")]
 | 
			
		||||
    [InlineData("dog --name Rufus --alive:true --good-boy:true 4 12", 4, 12, true, true, "Rufus")]
 | 
			
		||||
    [InlineData("dog --name Rufus --good-boy:true --alive:true 4 12", 4, 12, true, true, "Rufus")]
 | 
			
		||||
 | 
			
		||||
    // Inject the command arguments in between the options
 | 
			
		||||
    [InlineData("dog 4 12 --good-boy:true --name Rufus --alive:true", 4, 12, true, true, "Rufus")]
 | 
			
		||||
    [InlineData("dog 4 --good-boy:true 12 --name Rufus --alive:true", 4, 12, true, true, "Rufus")]
 | 
			
		||||
    [InlineData("dog --good-boy:true 4 12 --name Rufus --alive:true", 4, 12, true, true, "Rufus")]
 | 
			
		||||
    [InlineData("dog --good-boy:true 4 --name Rufus 12 --alive:true", 4, 12, true, true, "Rufus")]
 | 
			
		||||
    [InlineData("dog --name Rufus --alive:true 4 12 --good-boy:true", 4, 12, true, true, "Rufus")]
 | 
			
		||||
    [InlineData("dog --name Rufus --alive:true 4 --good-boy:true 12", 4, 12, true, true, "Rufus")]
 | 
			
		||||
 | 
			
		||||
    // Inject the command arguments in between the options (all flag values set to false)
 | 
			
		||||
    [InlineData("dog 4 12 --good-boy:false --name Rufus --alive:false", 4, 12, false, false, "Rufus")]
 | 
			
		||||
    [InlineData("dog 4 --good-boy:false 12 --name Rufus --alive:false", 4, 12, false, false, "Rufus")]
 | 
			
		||||
    [InlineData("dog --good-boy:false 4 12 --name Rufus --alive:false", 4, 12, false, false, "Rufus")]
 | 
			
		||||
    [InlineData("dog --good-boy:false 4 --name Rufus 12 --alive:false", 4, 12, false, false, "Rufus")]
 | 
			
		||||
    [InlineData("dog --name Rufus --alive:false 4 12 --good-boy:false", 4, 12, false, false, "Rufus")]
 | 
			
		||||
    [InlineData("dog --name Rufus --alive:false 4 --good-boy:false 12", 4, 12, false, false, "Rufus")]
 | 
			
		||||
    public void Should_Set_Option_Before_Argument(string arguments, int legs, int age, bool goodBoy, bool isAlive, string name)
 | 
			
		||||
    {
 | 
			
		||||
        // Given
 | 
			
		||||
        var app = new CommandAppTester();
 | 
			
		||||
        app.Configure(config =>
 | 
			
		||||
        {
 | 
			
		||||
            config.PropagateExceptions();
 | 
			
		||||
            config.AddCommand<DogCommand>("dog");
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        // When
 | 
			
		||||
        var result = app.Run(arguments.Split(' '));
 | 
			
		||||
 | 
			
		||||
        // Then
 | 
			
		||||
        result.ExitCode.ShouldBe(0);
 | 
			
		||||
        result.Settings.ShouldBeOfType<DogSettings>().And(settings =>
 | 
			
		||||
        {
 | 
			
		||||
    [InlineData("dog --alive 4 12 --name Rufus", 4, 12, false, true, "Rufus")]
 | 
			
		||||
    [InlineData("dog --alive=true 4 12 --name Rufus", 4, 12, false, true, "Rufus")]
 | 
			
		||||
    [InlineData("dog --alive:true 4 12 --name Rufus", 4, 12, false, true, "Rufus")]
 | 
			
		||||
    [InlineData("dog --alive --good-boy 4 12 --name Rufus", 4, 12, true, true, "Rufus")]
 | 
			
		||||
    [InlineData("dog --alive=true --good-boy=true 4 12 --name Rufus", 4, 12, true, true, "Rufus")]
 | 
			
		||||
    [InlineData("dog --alive:true --good-boy:true 4 12 --name Rufus", 4, 12, true, true, "Rufus")]
 | 
			
		||||
    [InlineData("dog --alive --good-boy --name Rufus 4 12", 4, 12, true, true, "Rufus")]
 | 
			
		||||
    [InlineData("dog --alive=true --good-boy=true --name Rufus 4 12", 4, 12, true, true, "Rufus")]
 | 
			
		||||
    [InlineData("dog --alive:true --good-boy:true --name Rufus 4 12", 4, 12, true, true, "Rufus")]
 | 
			
		||||
 | 
			
		||||
    // Short options
 | 
			
		||||
    [InlineData("dog -a 4 12 --name Rufus", 4, 12, false, true, "Rufus")]
 | 
			
		||||
    [InlineData("dog -a=true 4 12 --name Rufus", 4, 12, false, true, "Rufus")]
 | 
			
		||||
    [InlineData("dog -a:true 4 12 --name Rufus", 4, 12, false, true, "Rufus")]
 | 
			
		||||
    [InlineData("dog -a --good-boy 4 12 --name Rufus", 4, 12, true, true, "Rufus")]
 | 
			
		||||
    [InlineData("dog -a=true -g=true 4 12 --name Rufus", 4, 12, true, true, "Rufus")]
 | 
			
		||||
    [InlineData("dog -a:true -g:true 4 12 --name Rufus", 4, 12, true, true, "Rufus")]
 | 
			
		||||
    [InlineData("dog -a -g --name Rufus 4 12", 4, 12, true, true, "Rufus")]
 | 
			
		||||
    [InlineData("dog -a=true -g=true --name Rufus 4 12", 4, 12, true, true, "Rufus")]
 | 
			
		||||
    [InlineData("dog -a:true -g:true --name Rufus 4 12", 4, 12, true, true, "Rufus")]
 | 
			
		||||
 | 
			
		||||
    // Switch around ordering of the options
 | 
			
		||||
    [InlineData("dog --good-boy:true --name Rufus --alive:true 4 12", 4, 12, true, true, "Rufus")]
 | 
			
		||||
    [InlineData("dog --name Rufus --alive:true --good-boy:true 4 12", 4, 12, true, true, "Rufus")]
 | 
			
		||||
    [InlineData("dog --name Rufus --good-boy:true --alive:true 4 12", 4, 12, true, true, "Rufus")]
 | 
			
		||||
 | 
			
		||||
    // Inject the command arguments in between the options
 | 
			
		||||
    [InlineData("dog 4 12 --good-boy:true --name Rufus --alive:true", 4, 12, true, true, "Rufus")]
 | 
			
		||||
    [InlineData("dog 4 --good-boy:true 12 --name Rufus --alive:true", 4, 12, true, true, "Rufus")]
 | 
			
		||||
    [InlineData("dog --good-boy:true 4 12 --name Rufus --alive:true", 4, 12, true, true, "Rufus")]
 | 
			
		||||
    [InlineData("dog --good-boy:true 4 --name Rufus 12 --alive:true", 4, 12, true, true, "Rufus")]
 | 
			
		||||
    [InlineData("dog --name Rufus --alive:true 4 12 --good-boy:true", 4, 12, true, true, "Rufus")]
 | 
			
		||||
    [InlineData("dog --name Rufus --alive:true 4 --good-boy:true 12", 4, 12, true, true, "Rufus")]
 | 
			
		||||
 | 
			
		||||
    // Inject the command arguments in between the options (all flag values set to false)
 | 
			
		||||
    [InlineData("dog 4 12 --good-boy:false --name Rufus --alive:false", 4, 12, false, false, "Rufus")]
 | 
			
		||||
    [InlineData("dog 4 --good-boy:false 12 --name Rufus --alive:false", 4, 12, false, false, "Rufus")]
 | 
			
		||||
    [InlineData("dog --good-boy:false 4 12 --name Rufus --alive:false", 4, 12, false, false, "Rufus")]
 | 
			
		||||
    [InlineData("dog --good-boy:false 4 --name Rufus 12 --alive:false", 4, 12, false, false, "Rufus")]
 | 
			
		||||
    [InlineData("dog --name Rufus --alive:false 4 12 --good-boy:false", 4, 12, false, false, "Rufus")]
 | 
			
		||||
    [InlineData("dog --name Rufus --alive:false 4 --good-boy:false 12", 4, 12, false, false, "Rufus")]
 | 
			
		||||
    public void Should_Set_Option_Before_Argument(string arguments, int legs, int age, bool goodBoy, bool isAlive, string name)
 | 
			
		||||
    {
 | 
			
		||||
        // Given
 | 
			
		||||
        var app = new CommandAppTester();
 | 
			
		||||
        app.Configure(config =>
 | 
			
		||||
        {
 | 
			
		||||
            config.PropagateExceptions();
 | 
			
		||||
            config.AddCommand<DogCommand>("dog");
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        // When
 | 
			
		||||
        var result = app.Run(arguments.Split(' '));
 | 
			
		||||
 | 
			
		||||
        // Then
 | 
			
		||||
        result.ExitCode.ShouldBe(0);
 | 
			
		||||
        result.Settings.ShouldBeOfType<DogSettings>().And(settings =>
 | 
			
		||||
        {
 | 
			
		||||
            settings.Legs.ShouldBe(legs);
 | 
			
		||||
            settings.Age.ShouldBe(age);
 | 
			
		||||
            settings.GoodBoy.ShouldBe(goodBoy);
 | 
			
		||||
            settings.IsAlive.ShouldBe(isAlive);
 | 
			
		||||
            settings.Name.ShouldBe(name);
 | 
			
		||||
        });
 | 
			
		||||
            settings.Name.ShouldBe(name);
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    [Fact]
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user