Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions CommandLineParser.Tests/CommandLineParserTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ public void AutoExecuteCommandsWithExceptionDoesntCrashTheParser()

Assert.True(result.HasErrors);

Assert.Equal(ex, result.Errors.First());
Assert.Equal(ex, result.Errors.First().GetBaseException());
}

[Fact]
Expand All @@ -202,7 +202,7 @@ public async Task AutoExecuteCommandsWithExceptionDoesntCrashTheParserAsync()

Assert.True(result.HasErrors);

Assert.Equal(ex, result.Errors.First());
Assert.Equal(ex, result.Errors.First().GetBaseException());
}

[Fact]
Expand Down
14 changes: 6 additions & 8 deletions CommandLineParser.Tests/Usage/HelpDisplayCommandTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,8 @@ public void TestHelpDisplayFiresCorrectly(string[] args, bool fires)
var usagePrinterMock = new Mock<IUsagePrinter>();

usagePrinterMock.Setup(mock => mock.PrintUsage()).Callback(() => calledFlag = true);
usagePrinterMock.Setup(mock => mock.PrintUsage(It.IsAny<IArgument>())).Callback(() => calledFlag = true);
usagePrinterMock.Setup(mock => mock.PrintUsage(It.IsAny<ICommandLineCommand>())).Callback(() => calledFlag = true);
usagePrinterMock.Setup(mock => mock.PrintUsage(It.IsAny<ICommandLineOption>())).Callback(() => calledFlag = true);
usagePrinterMock.Setup(mock => mock.PrintCommandUsage(It.IsAny<ICommandLineCommand>())).Callback(() => calledFlag = true);
usagePrinterMock.Setup(mock => mock.PrintOptionUsage(It.IsAny<ICommandLineOption>())).Callback(() => calledFlag = true);

var parser = new CommandLineParser<Options>
{
Expand All @@ -41,7 +40,7 @@ public void TestHelpDisplayFiresCorrectly(string[] args, bool fires)

parser.Parse(args);

Assert.Equal<bool>(fires, calledFlag);
Assert.Equal(fires, calledFlag);
}

[Theory]
Expand All @@ -60,9 +59,8 @@ public async Task TestHelpDisplayFiresCorrectlyAsync(string[] args, bool fires)
var usagePrinterMock = new Mock<IUsagePrinter>();

usagePrinterMock.Setup(mock => mock.PrintUsage()).Callback(() => calledFlag = true);
usagePrinterMock.Setup(mock => mock.PrintUsage(It.IsAny<IArgument>())).Callback(() => calledFlag = true);
usagePrinterMock.Setup(mock => mock.PrintUsage(It.IsAny<ICommandLineCommand>())).Callback(() => calledFlag = true);
usagePrinterMock.Setup(mock => mock.PrintUsage(It.IsAny<ICommandLineOption>())).Callback(() => calledFlag = true);
usagePrinterMock.Setup(mock => mock.PrintCommandUsage(It.IsAny<ICommandLineCommand>())).Callback(() => calledFlag = true);
usagePrinterMock.Setup(mock => mock.PrintOptionUsage(It.IsAny<ICommandLineOption>())).Callback(() => calledFlag = true);

var parser = new CommandLineParser<Options>
{
Expand All @@ -75,7 +73,7 @@ public async Task TestHelpDisplayFiresCorrectlyAsync(string[] args, bool fires)

await parser.ParseAsync(args);

Assert.Equal<bool>(fires, calledFlag);
Assert.Equal(fires, calledFlag);
}

public class Options
Expand Down
25 changes: 15 additions & 10 deletions CommandLineParser.Tests/Usage/UsagePrinterTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ public void UsagePrinterPrintsOptionCorrectly()

parser.Parse(new[] { "-o", "--help" });

printerMock.Verify(mock => mock.PrintUsage(It.IsAny<IArgument>()), Times.Once());
printerMock.Verify(mock => mock.PrintOptionUsage(It.IsAny<ICommandLineOption>()), Times.Once());
}

[Fact]
Expand All @@ -105,7 +105,7 @@ public void UsagePrinterPrintsCommandCorrectly()

parser.Parse(new[] { "-o", "bla", "cmd", "--help" });

printerMock.Verify(mock => mock.PrintUsage(It.IsAny<IArgument>()), Times.Once());
printerMock.Verify(mock => mock.PrintCommandUsage(It.IsAny<ICommandLineCommand>()), Times.Once());
}

[Theory]
Expand All @@ -123,41 +123,46 @@ public void CustomInvokedPrinterWorksCorrectly(string[] args, bool cmdPassed, bo

var parser = new CommandLineParser<UsagePrinterGetsCalledOptions>(parserOptions);

parser.Printer = new UsagePrinter(parserOptions, parser, builderMock.Object);
parser.Printer = new UsagePrinter(parser, builderMock.Object);

parser.AddCommand<UsagePrinterCommandOptions>()
.Name("cmd")
.Required();

var result = parser.Parse(args);

builderMock.Verify(mock => mock.Print(), Times.Never());
builderMock.Verify(mock => mock.PrintCommand(It.IsAny<string>(), It.IsAny<ICommandLineCommandContainer>()), Times.Never());
builderMock.Verify(mock => mock.PrintOption(It.IsAny<ICommandLineOption>()), Times.Never());
builderMock.Verify(mock => mock.Build(), Times.Never());
builderMock.Verify(mock => mock.AddCommand(It.IsAny<string>(), It.IsAny<ICommandLineCommandContainer>()), Times.Never());
builderMock.Verify(mock => mock.AddOption(It.IsAny<ICommandLineOption>()), Times.Never());

if (result.HelpRequested)
{
parser.Printer.PrintUsage(result.HelpRequestedFor);
}

if (result.HasErrors)
{
foreach (var err in result.Errors)
{
if (!(err is BaseParserException baseParserException)) continue;
if (!(err is BaseParserException baseParserException))
{
continue;
}

parser.Printer.PrintUsage(baseParserException.Argument);
}
}

builderMock.Verify(
mock => mock.Print(),
mock => mock.Build(),
ToTimes(result.HelpRequested || result.HasErrors));

builderMock.Verify(
mock => mock.PrintCommand(It.IsAny<string>(), It.IsAny<ICommandLineCommandContainer>()),
mock => mock.AddCommand(It.IsAny<string>(), It.IsAny<ICommandLineCommand>()),
ToTimes(cmdPassed));

builderMock.Verify(
mock => mock.PrintOption(It.IsAny<ICommandLineOption>()),
mock => mock.AddOption(It.IsAny<ICommandLineOption>()),
ToTimes(optPassed));
}

Expand Down
70 changes: 62 additions & 8 deletions CommandLineParser/Abstractions/Usage/IUsageBuilder.cs
Original file line number Diff line number Diff line change
@@ -1,16 +1,70 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using MatthiWare.CommandLine.Abstractions.Command;

namespace MatthiWare.CommandLine.Abstractions.Usage
{
/// <summary>
/// Output builder
/// </summary>
public interface IUsageBuilder
{
void Print();
void PrintUsage(string name, bool hasOptions, bool hasCommands);
void PrintOptions(IEnumerable<ICommandLineOption> options);
void PrintOption(ICommandLineOption option);
void PrintCommandDescriptions(IEnumerable<ICommandLineCommand> commands);
void PrintCommandDescription(ICommandLineCommand command);
void PrintCommand(string name, ICommandLineCommandContainer container);
/// <summary>
/// Generates the output
/// </summary>
/// <returns>Output string</returns>
string Build();

/// <summary>
/// Add usage
/// </summary>
/// <param name="name">Name of the applpication</param>
/// <param name="hasOptions">Indicates if the output contains options</param>
/// <param name="hasCommands">Indicates if the output contains commands</param>
void AddUsage(string name, bool hasOptions, bool hasCommands);

/// <summary>
/// Add all options
/// </summary>
/// <param name="options"></param>
void AddOptions(IEnumerable<ICommandLineOption> options);

/// <summary>
/// Add a specific option
/// </summary>
/// <param name="option"></param>
void AddOption(ICommandLineOption option);

/// <summary>
/// Adds all command descriptions
/// </summary>
/// <param name="commands"></param>
void AddCommandDescriptions(IEnumerable<ICommandLineCommand> commands);

/// <summary>
/// Adds a specific command description
/// </summary>
/// <param name="command"></param>
void AddCommandDescription(ICommandLineCommand command);

/// <summary>
/// Adds a command to the output builder
/// </summary>
/// <param name="name"></param>
/// <param name="command"></param>
void AddCommand(string name, ICommandLineCommand command);

/// <summary>
/// Adds a command to the output builder
/// </summary>
/// <param name="name"></param>
/// <param name="container"></param>
void AddCommand(string name, ICommandLineCommandContainer container);

/// <summary>
/// Adds the errors to the output builder
/// </summary>
/// <param name="errors"></param>
void AddErrors(IReadOnlyCollection<Exception> errors);
}
}
29 changes: 29 additions & 0 deletions CommandLineParser/Abstractions/Usage/IUsagePrinter.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using MatthiWare.CommandLine.Abstractions.Command;
using System;
using System.Collections.Generic;

namespace MatthiWare.CommandLine.Abstractions.Usage
{
Expand All @@ -7,26 +9,53 @@ namespace MatthiWare.CommandLine.Abstractions.Usage
/// </summary>
public interface IUsagePrinter
{
/// <summary>
/// Gets the usage builder <see cref="IUsageBuilder"/>
/// </summary>
IUsageBuilder Builder { get; }

/// <summary>
/// Print global usage
/// </summary>
void PrintUsage();

/// <summary>
/// Print an argument
/// </summary>
/// <param name="argument">The given argument</param>
[Obsolete("Use PrintCommandUsage or PrintOptionUsage instead")]
void PrintUsage(IArgument argument);

/// <summary>
/// Print command usage
/// </summary>
/// <param name="command">The given command</param>
[Obsolete("Use PrintCommandUsage instead")]
void PrintUsage(ICommandLineCommand command);

/// <summary>
/// Print command usage
/// </summary>
/// <param name="command">The given command</param>
void PrintCommandUsage(ICommandLineCommand command);

/// <summary>
/// Print option usage
/// </summary>
/// <param name="option">The given option</param>
[Obsolete("Use PrintCommandUsage instead")]
void PrintUsage(ICommandLineOption option);

/// <summary>
/// Print option usage
/// </summary>
/// <param name="option">The given option</param>
void PrintOptionUsage(ICommandLineOption option);

/// <summary>
/// Print errors
/// </summary>
/// <param name="errors">list of errors</param>
void PrintErrors(IReadOnlyCollection<Exception> errors);
}
}
Loading