Skip to content

Commit 2f2c804

Browse files
authored
Add NO_COLOR support (#69)
* Add support for NO_COLOR fixes #52 * Update xml documentation * Add tests * Fix styling issue
1 parent 11be53b commit 2f2c804

File tree

6 files changed

+175
-7
lines changed

6 files changed

+175
-7
lines changed
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
using MatthiWare.CommandLine.Abstractions;
2+
using MatthiWare.CommandLine.Abstractions.Usage;
3+
using MatthiWare.CommandLine.Core.Attributes;
4+
using MatthiWare.CommandLine.Core.Usage;
5+
using Moq;
6+
using System;
7+
using System.Collections.Generic;
8+
using System.Text;
9+
using Xunit;
10+
11+
namespace MatthiWare.CommandLine.Tests.Usage
12+
{
13+
[Collection("Non-Parallel Collection")]
14+
public class NoColorOutputTests
15+
{
16+
private readonly CommandLineParser<Options> parser;
17+
private readonly IEnvironmentVariablesService variablesService;
18+
private Action<ConsoleColor> consoleColorGetter;
19+
private bool variableServiceResult;
20+
private readonly UsagePrinter printer;
21+
22+
public NoColorOutputTests()
23+
{
24+
var envMock = new Mock<IEnvironmentVariablesService>();
25+
envMock.SetupGet(env => env.NoColorRequested).Returns(() => variableServiceResult);
26+
27+
variablesService = envMock.Object;
28+
29+
var usageBuilderMock = new Mock<IUsageBuilder>();
30+
usageBuilderMock.Setup(m => m.AddErrors(It.IsAny<IReadOnlyCollection<Exception>>())).Callback(() =>
31+
{
32+
consoleColorGetter(printer.m_currentConsoleColor);
33+
});
34+
35+
parser = new CommandLineParser<Options>();
36+
37+
printer = new UsagePrinter(parser, usageBuilderMock.Object, variablesService);
38+
39+
parser.Printer = printer;
40+
}
41+
42+
[Fact]
43+
public void CheckUsageOutputRespectsNoColor()
44+
{
45+
ParseAndCheckNoColor(false);
46+
ParseAndCheckNoColor(true);
47+
}
48+
49+
private void ParseAndCheckNoColor(bool noColorOuput)
50+
{
51+
consoleColorGetter = noColorOuput ? (Action<ConsoleColor>)AssertNoColor : AssertColor;
52+
53+
variableServiceResult = noColorOuput;
54+
55+
parser.Parse(new string[] { "alpha" });
56+
}
57+
58+
private void AssertNoColor(ConsoleColor color)
59+
{
60+
Assert.True(variablesService.NoColorRequested);
61+
Assert.NotEqual(ConsoleColor.Red, color);
62+
}
63+
64+
private void AssertColor(ConsoleColor color)
65+
{
66+
Assert.False(variablesService.NoColorRequested);
67+
Assert.Equal(ConsoleColor.Red, color);
68+
}
69+
70+
private class Options
71+
{
72+
[Required, Name("b")]
73+
public bool MyBool { get; set; }
74+
}
75+
}
76+
}

CommandLineParser.Tests/XUnitExtensions.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System;
22
using System.Linq.Expressions;
33
using MatthiWare.CommandLine.Abstractions.Parsing;
4+
using Xunit;
45

56
namespace MatthiWare.CommandLine.Tests
67
{
@@ -31,4 +32,11 @@ public static bool AssertNoErrors<T>(this IParserResult<T> result, bool shouldTh
3132
return false;
3233
}
3334
}
35+
36+
#pragma warning disable SA1402 // FileMayOnlyContainASingleType
37+
[CollectionDefinition("Non-Parallel Collection", DisableParallelization = true)]
38+
public class NonParallelCollection
39+
{
40+
}
41+
#pragma warning restore SA1402 // FileMayOnlyContainASingleType
3442
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
namespace MatthiWare.CommandLine.Abstractions.Usage
2+
{
3+
/// <summary>
4+
/// Environment variables
5+
/// </summary>
6+
public interface IEnvironmentVariablesService
7+
{
8+
/// <summary>
9+
/// Inidicates if NO_COLOR environment variable has been set
10+
/// https://no-color.org/
11+
/// </summary>
12+
bool NoColorRequested { get; }
13+
}
14+
}

CommandLineParser/CommandLineParser.xml

Lines changed: 30 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
using MatthiWare.CommandLine.Abstractions.Usage;
2+
using System;
3+
4+
namespace MatthiWare.CommandLine.Core.Usage
5+
{
6+
/// <inheritdoc/>
7+
public class EnvironmentVariableService : IEnvironmentVariablesService
8+
{
9+
private const string NoColorId = "NO_COLOR";
10+
11+
/// <inheritdoc/>
12+
public bool NoColorRequested => Environment.GetEnvironmentVariable(NoColorId) != null;
13+
}
14+
}

CommandLineParser/Core/Usage/UsagePrinter.cs

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,30 +9,57 @@ namespace MatthiWare.CommandLine.Core.Usage
99
/// <inheritdoc/>
1010
public class UsagePrinter : IUsagePrinter
1111
{
12+
private readonly IEnvironmentVariablesService environmentVariablesService;
13+
1214
protected ICommandLineCommandContainer Container { get; }
1315

1416
/// <inheritdoc/>
1517
public IUsageBuilder Builder { get; }
1618

17-
/// <inheritdoc/>
19+
internal ConsoleColor m_currentConsoleColor = ConsoleColor.Gray;
20+
21+
/// <summary>
22+
/// Creates a new CLI output usage printer
23+
/// </summary>
24+
/// <param name="container"></param>
25+
/// <param name="builder"></param>
1826
public UsagePrinter(ICommandLineCommandContainer container, IUsageBuilder builder)
27+
: this(container, builder, new EnvironmentVariableService())
28+
{ }
29+
30+
/// <summary>
31+
/// Creates a new CLI output usage printer
32+
/// </summary>
33+
/// <param name="container"></param>
34+
/// <param name="builder"></param>
35+
/// <param name="environmentVariablesService"></param>
36+
public UsagePrinter(ICommandLineCommandContainer container, IUsageBuilder builder, IEnvironmentVariablesService environmentVariablesService)
1937
{
20-
Container = container;
21-
Builder = builder;
38+
Container = container ?? throw new ArgumentNullException(nameof(container));
39+
Builder = builder ?? throw new ArgumentNullException(nameof(builder));
40+
this.environmentVariablesService = environmentVariablesService ?? throw new ArgumentNullException(nameof(environmentVariablesService));
2241
}
2342

2443
/// <inheritdoc/>
2544
public virtual void PrintErrors(IReadOnlyCollection<Exception> errors)
2645
{
27-
var previousColor = Console.ForegroundColor;
46+
bool canOutputColor = !this.environmentVariablesService.NoColorRequested;
2847

29-
Console.ForegroundColor = ConsoleColor.Red;
48+
if (canOutputColor)
49+
{
50+
m_currentConsoleColor = ConsoleColor.Red;
51+
Console.ForegroundColor = ConsoleColor.Red;
52+
}
3053

3154
Builder.AddErrors(errors);
3255

3356
Console.Error.WriteLine(Builder.Build());
3457

35-
Console.ForegroundColor = previousColor;
58+
if (canOutputColor)
59+
{
60+
m_currentConsoleColor = ConsoleColor.Gray;
61+
Console.ResetColor();
62+
}
3663

3764
Console.WriteLine();
3865
}

0 commit comments

Comments
 (0)