Skip to content

Commit 31f6d77

Browse files
committed
Add examples to --help output
1 parent 44e6f97 commit 31f6d77

File tree

1 file changed

+80
-20
lines changed

1 file changed

+80
-20
lines changed

src/ProfileTool/Program.cs

Lines changed: 80 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
using System.CommandLine;
2+
using System.CommandLine.Builder;
3+
using System.CommandLine.Help;
4+
using System.CommandLine.Parsing;
25
using System.Diagnostics;
36
using System.Globalization;
7+
using System.Linq;
48
using System.Text.Json;
59
using System.Threading;
610
using Asynkron.Profiler;
@@ -16,25 +20,59 @@ void PrintSection(string text)
1620
Console.WriteLine(text);
1721
}
1822

19-
void PrintUsageExamples()
23+
IReadOnlyList<string> GetUsageExampleLines()
2024
{
21-
Console.WriteLine("Examples:");
22-
Console.WriteLine();
23-
Console.WriteLine("CPU profiling:");
24-
Console.WriteLine(" asynkron-profiler --cpu -- dotnet run MyProject.sln");
25-
Console.WriteLine(" asynkron-profiler --cpu --calltree-depth 5 -- dotnet run MyProject.sln");
26-
Console.WriteLine(" asynkron-profiler --cpu --input ./profile-output/app.speedscope.json");
27-
Console.WriteLine();
28-
Console.WriteLine("Memory profiling:");
29-
Console.WriteLine(" asynkron-profiler --memory -- dotnet test");
30-
Console.WriteLine(" asynkron-profiler --memory --input ./profile-output/app.nettrace");
31-
Console.WriteLine();
32-
Console.WriteLine("Heap snapshot:");
33-
Console.WriteLine(" asynkron-profiler --heap -- dotnet run MyProject.sln");
34-
Console.WriteLine(" asynkron-profiler --heap --input ./profile-output/app.gcdump");
35-
Console.WriteLine();
36-
Console.WriteLine("General:");
37-
Console.WriteLine(" asynkron-profiler --help");
25+
return new[]
26+
{
27+
"Examples:",
28+
"",
29+
"CPU profiling:",
30+
" asynkron-profiler --cpu -- dotnet run MyProject.sln",
31+
" asynkron-profiler --cpu --calltree-depth 5 -- dotnet run MyProject.sln",
32+
" asynkron-profiler --cpu --input ./profile-output/app.speedscope.json",
33+
"",
34+
"Memory profiling:",
35+
" asynkron-profiler --memory -- dotnet test",
36+
" asynkron-profiler --memory --root \"MyNamespace\" -- dotnet test",
37+
" asynkron-profiler --memory --input ./profile-output/app.nettrace",
38+
"",
39+
"Heap snapshot:",
40+
" asynkron-profiler --heap -- dotnet run MyProject.sln",
41+
" asynkron-profiler --heap --input ./profile-output/app.gcdump",
42+
"",
43+
"Render existing traces:",
44+
" asynkron-profiler --input ./profile-output/app.nettrace",
45+
" asynkron-profiler --input ./profile-output/app.speedscope.json --cpu",
46+
" asynkron-profiler --input ./profile-output/app.etlx --memory",
47+
"",
48+
"General:",
49+
" asynkron-profiler --help"
50+
};
51+
}
52+
53+
void WriteUsageExamples(TextWriter writer)
54+
{
55+
foreach (var line in GetUsageExampleLines())
56+
{
57+
writer.WriteLine(line);
58+
}
59+
}
60+
61+
int GetHelpWidth()
62+
{
63+
if (Console.IsOutputRedirected)
64+
{
65+
return 200;
66+
}
67+
68+
try
69+
{
70+
return Math.Max(80, Console.WindowWidth);
71+
}
72+
catch
73+
{
74+
return 120;
75+
}
3876
}
3977

4078
(bool Success, string StdOut, string StdErr) RunProcess(
@@ -1757,7 +1795,7 @@ string BuildCommandDescription(string[] command)
17571795
if (command.Length == 0)
17581796
{
17591797
AnsiConsole.MarkupLine("[red]No command provided.[/]");
1760-
PrintUsageExamples();
1798+
WriteUsageExamples(Console.Out);
17611799
return;
17621800
}
17631801

@@ -1812,4 +1850,26 @@ string BuildCommandDescription(string[] command)
18121850
}
18131851
});
18141852

1815-
return await rootCommand.InvokeAsync(args);
1853+
void ExamplesSection(HelpContext context)
1854+
{
1855+
if (!ReferenceEquals(context.Command, rootCommand))
1856+
{
1857+
return;
1858+
}
1859+
1860+
context.Output.WriteLine();
1861+
WriteUsageExamples(context.Output);
1862+
}
1863+
1864+
var parser = new CommandLineBuilder(rootCommand)
1865+
.UseDefaults()
1866+
.UseHelpBuilder(_ =>
1867+
{
1868+
var helpBuilder = new HelpBuilder(LocalizationResources.Instance, GetHelpWidth());
1869+
helpBuilder.CustomizeLayout(context =>
1870+
HelpBuilder.Default.GetLayout().Concat(new HelpSectionDelegate[] { ExamplesSection }));
1871+
return helpBuilder;
1872+
})
1873+
.Build();
1874+
1875+
return await parser.InvokeAsync(args);

0 commit comments

Comments
 (0)