spectre.console icon indicating copy to clipboard operation
spectre.console copied to clipboard

HelpProvider renders some formatting markup even with NO_COLOR

Open kzu opened this issue 1 year ago • 6 comments

To Reproduce

dotnet tool update -g dotnet-trx
$env:NO_COLOR=1
trx --help

Raw output:

USAGE:
    trx [OPTIONS]

OPTIONS:
                          DEFAULT                                               
    -h, --help                       Prints help information                    
    -p, --path                       Optional base directory for *.trx files    
                                     discovery. Defaults to current directory   
    -o, --output                     Include test output                        
    -r, --recursive       �[1mTrue�[0m       Recursively search for *.trx files         
        --skipped         �[1mTrue�[0m       Include skipped tests                      
        --no-exit-code               Do not return a -1 exit code on test       
                                     failures                                   
        --version                    Show version information                   
        --gh-comment      �[1mTrue�[0m       Report as GitHub PR comment                
        --gh-summary      �[1mTrue�[0m       Report as GitHub step summary              

Expected behavior Renders text only, with no bold or any other styles applied.

Screenshots Default values have bold style applied:

image

The importance of the issue is that it prevents having an automated way to self-document a CLI tool via the package readme, automatically updated after compile with up-to-date usage info, as shown in https://www.cazzulino.com/auto-doc-cli.html

kzu avatar Jul 17 '24 06:07 kzu

I got a draft PR just to explore what the changes might be. Feel free to suggest alternatives. All existing tests pass fine, but I could not find unit tests specifically exercising the HelpProvider itself, to add a failing test and make it pass :). But the new output after the PR looks as I expected, without any formatting whatesoever:

USAGE:
    trx [OPTIONS]

OPTIONS:
                          DEFAULT                                               
    -h, --help                       Prints help information                    
    -p, --path                       Optional base directory for *.trx files    
                                     discovery. Defaults to current directory   
    -o, --output                     Include test output                        
    -r, --recursive       True       Recursively search for *.trx files         
        --skipped         True       Include skipped tests                      
        --no-exit-code               Do not return a -1 exit code on test       
                                     failures                                   
        --version                    Show version information                   
        --gh-comment      True       Report as GitHub PR comment                
        --gh-summary      True       Report as GitHub step summary        

kzu avatar Jul 17 '24 06:07 kzu

NO_COLOR only prevents outputting colors, not ANSI control codes or CSI sequences related to style.

patriksvensson avatar Jul 17 '24 07:07 patriksvensson

To automate output and get rid of ANSI sequences, you should disable ANSI completely using the console profile and add a switch in your application. NO_COLOR is not the way to go here.

You can also use a console recorder (https://spectreconsole.net/api/spectre.console/recorder/) to record the output.

patriksvensson avatar Jul 17 '24 07:07 patriksvensson

Do you think there's an opportunity to provide something like this at least for the restricted use case of rendering text-only versions of help for the purposes of self-updating static docs for a tool?

kzu avatar Jul 17 '24 20:07 kzu

Got a workaround for now in my app:

var app = new CommandApp();
// ...
app.Configure(config =>
{
  if (Environment.GetEnvironmentVariables().Contains("NO_COLOR") &&
      config.Settings.HelpProviderStyles?.Options is { } options)
      options.DefaultValue = Style.Plain;
});

kzu avatar Jul 17 '24 21:07 kzu

Hello @kzu,

FYI. there is a unit test demonstrating a completely unstyled help output, see:

https://github.com/spectreconsole/spectre.console/blob/42fd801876398aea555dc93fcfe4bc0525bd2df4/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Help.cs#L413

That results in Style.Plain being used throughout the help provider, eg:

https://github.com/spectreconsole/spectre.console/blob/42fd801876398aea555dc93fcfe4bc0525bd2df4/src/Spectre.Console.Cli/Help/HelpProvider.cs#L173

I would probably recommend you follow this approach instead, which is very similar to yours, but would prevent any future issues with styling being added to other sections in the help writer output in future releases (nb. no plans to do so, just saying).

FrankRay78 avatar Aug 08 '24 20:08 FrankRay78

@FrankRay78 that didn't work. It seems it's being re-set by someone else. The default values are bold even though I set the help styles to null:

image

kzu avatar Sep 02 '24 20:09 kzu

Thanks for testing @kzu, I'll bump this up my list of things to fix.

FrankRay78 avatar Sep 02 '24 21:09 FrankRay78

Hello @kzu, the help provider styling is working as expected for me. I have put together a MRE below, along with screenshots, and it would be great if you could execute the same and tell me what happens. My test platform: Windows 10, Terminal, Command Prompt (with OOTB settings), Spectre.Console 0.49.1

Scenario 1:

Build the following console app:

using System.ComponentModel;
using Spectre.Console.Cli;

public sealed class DefaultCommand : Command<DefaultCommand.DefaultCommandSettings>
{
    public sealed class DefaultCommandSettings : CommandSettings
    {
        [CommandOption("-p|--port <PORT>")]
        [Description("Port to use. Defaults to [blue]8080[/]. Use [blue]0[/] for a dynamic port.")]
        [DefaultValue(500)]
        public int Port { get; set; }
    }

    public override int Execute(CommandContext context, DefaultCommandSettings settings)
    {
        return 0;
    }
}

public class Program
{
    public static int Main(string[] args)
    {
        var app = new CommandApp<DefaultCommand>();

        return app.Run(args);
    }
}

The following output is produced when the console app is run:

image

Scenario 2:

In the same console as above, execute the following set NO_COLOR=1

The following output is produced when the console app is run:

image

Scenario 3:

Update your console app as below, then rebuild it.

public class Program
{
    public static int Main(string[] args)
    {
        var app = new CommandApp<DefaultCommand>();

        //------------ I ADDED THE BELOW ------------//

        app.Configure(config =>
        {
            // Render an unstyled help text for maximum accessibility
            config.Settings.HelpProviderStyles = null;
        });

        //------------ I ADDED THE ABOVE ------------//

        return app.Run(args);
    }
}

In the same console as Scenario 2 (ie. NO_COLOR has been set to 1)

The following output is produced when the console app is run:

image

Scenario 4:

Open a new console (ie. NO_COLOR has not been set)

Use the console app built in Scenario 3 (ie. HelpProviderStyles set to null)

The following output is produced when the console app is run:

image

The output is unstyled except for hardcoded colours in the command settings:

[Description("Port to use. Defaults to [blue]8080[/]. Use [blue]0[/] for a dynamic port.")]

FrankRay78 avatar Sep 20 '24 15:09 FrankRay78

Thanks @FrankRay78 for that thorough test. I went back to it and tried it again (updated to latest), and things seem to be working now. So I'll close this now.

Thanks!

kzu avatar Sep 29 '24 04:09 kzu

My pleasure @kzu. Feel free to tag me in directly for any future command line / help generator issues. In the meantime, take care.

FrankRay78 avatar Oct 01 '24 13:10 FrankRay78