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
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@ System.CommandLine.Completions
System.CommandLine.Help
public class HelpAction : System.CommandLine.Invocation.SynchronousCommandLineAction
.ctor()
public System.Int32 MaxWidth { get; set; }
public System.Int32 Invoke(System.CommandLine.ParseResult parseResult)
public class HelpOption : System.CommandLine.Option
.ctor()
Expand Down
25 changes: 25 additions & 0 deletions src/System.CommandLine.Tests/HelpOptionTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,31 @@ public void The_users_can_print_help_output_of_a_subcommand()
output.ToString().Should().NotContain(RootDescription);
}

[Fact]
public void The_users_can_set_max_width()
{
string firstPart = new('a', count: 50);
string secondPart = new('b', count: 50);
string description = firstPart + secondPart;

RootCommand rootCommand = new(description);
rootCommand.Options.Clear();
rootCommand.Options.Add(new HelpOption()
{
Action = new HelpAction()
{
MaxWidth = 2 /* each line starts with two spaces */ + description.Length / 2
}
});
StringWriter output = new ();

rootCommand.Parse("--help").Invoke(new() { Output = output });

output.ToString().Should().NotContain(description);
output.ToString().Should().Contain($" {firstPart}{Environment.NewLine}");
output.ToString().Should().Contain($" {secondPart}{Environment.NewLine}");
}

private sealed class CustomizedHelpAction : SynchronousCommandLineAction
{
internal const string CustomUsageText = "This is custom command usage example.";
Expand Down
38 changes: 36 additions & 2 deletions src/System.CommandLine/Help/HelpAction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,47 @@ namespace System.CommandLine.Help
public sealed class HelpAction : SynchronousCommandLineAction
{
private HelpBuilder? _builder;
private int _maxWidth = -1;

/// <summary>
/// The maximum width in characters after which help output is wrapped.
/// </summary>
/// <remarks>It defaults to <see cref="Console.WindowWidth"/>.</remarks>
public int MaxWidth
{
get
{
if (_maxWidth < 0)
{
try
{
_maxWidth = Console.IsOutputRedirected ? int.MaxValue : Console.WindowWidth;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will something cause reevaluation on resizing the console host?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will something cause reevaluation on resizing the console host?

No. This value will be requested a moment before the help is going to be displayed. And in 99.9% of the cases that will be the last thing the program does before exit.

}
catch (Exception)
{
_maxWidth = int.MaxValue;
}
}

return _maxWidth;
}
set
{
if (value <= 0)
{
throw new ArgumentOutOfRangeException(nameof(value));
}

_maxWidth = value;
}
}

/// <summary>
/// Specifies an <see cref="Builder"/> to be used to format help output when help is requested.
/// </summary>
internal HelpBuilder Builder
{
get => _builder ??= new HelpBuilder(Console.IsOutputRedirected ? int.MaxValue : Console.WindowWidth);
get => _builder ??= new HelpBuilder(MaxWidth);
set => _builder = value ?? throw new ArgumentNullException(nameof(value));
}

Expand All @@ -32,4 +66,4 @@ public override int Invoke(ParseResult parseResult)
return 0;
}
}
}
}