Open dagilleland opened 1 year ago
And here's an embedded version of what I wrote (for those who prefer not to download the PDF above). Note that some links won't work (obviously) because it is currently part of a template repository I'm using for my students.
Estimated time: 1 hour
System.CommandLine was created to help developers build their own command-line applications. The primary goal was to handle all the "messy" parts of a typical CLI so that the developer can focus on the "real" purpose of their application. Specifically, the creators of the System.CommandLine had these motivations.
- Provide a parser that's independent of binding and invocation.
- Make the end user command line experience consistent and inclusive.
- A composable chain of responsibility for subcommand routing, middleware, directives, etc.
- Rich, adaptive output rendering
- Other things:
As such, their high-level goals for "creating great command line experiences" for developers include
As a new developer, you should have a basic understanding of C# programming (i.e.: variables, methods, flow-control statements, and simple OOP) as well as these specific concepts:
.csproj
file.
There are three core terms to understand when it comes to CLI applications.
In the vein of the traditional "Hello World"
™ application, the following code sample represents a command-line application that has an option to display the author of the program. Modify your Program.cs
so that it contains this code.
NOTE: For best results, you should manually type the following code into your
Program.cs
rather than just copying and pasting it. Remember, your primary goal here is to understand what the code is doing. Typing it out yourself (including all the comments) will slow down your thinking enough to help you figure out how to leverage the System.CommandLine for your own purposes in the future.
using System.CommandLine;
using System.CommandLine.Builder;
using System.CommandLine.Parsing;
internal class Program
{
private static void Main(string[] args)
{
// 1) Define the Options, Arguments, and SubCommands that your CLI will support
var authorOption = new Option<bool>("--author", "Display information about who created this program.");
// ^----^ ^--------^ ^--- description of the option (for --help) --------^
// | |
// | |_ The name of the option (i.e.: the "flag" send into our CLI app)
// |_ The data type this option will be converted to.
// - will return a true if "--author" is passed in and false if it is absent
// 2) Create a root command that represents the whole application (subcommands and all)
var rootCommand = new RootCommand("Sample CLI using System.CommandLine");
// ^--- description of this program ---^
// Add your option to your root command
rootCommand.AddOption(authorOption);
// Identify what method should be called in order to handle/process the root command
rootCommand.SetHandler<bool>(RunMainCommand, authorOption);
// ^----^ ^------------^ ^----------^
// | | |_ The Option<T> that will be converted into a T value.
// | | - The converted value will be passed into RunMainCommand
// | |_ The name of the method (delegate/action) that should be called
// | by System.CommandLine when it's done parsing the string[] args
// |_ The data type of the parameter for the RunMainCommand method.
// 3) Use the CommandLineBuilder to include additional configuration for your CLI app.
// Notice how the CommandLineBuilder provides a "fluent interface" for setting up
var myCommandLineApp = new CommandLineBuilder(rootCommand)
.UseDefaults() // This represents the configuration settings most commonly desired for CLI apps
.Build(); // This final call generates the "parser" object that will process/interpret the args
// 4) Run (invoke) your application by sending in the string[] args data from the Main method
myCommandLineApp.Invoke(args);
}
private static void RunMainCommand(bool showAuthorInformation)
{
if(showAuthorInformation)
{
Console.WriteLine("Username: stewdent"); // Your GitHub username
Console.WriteLine("Full name: Stewart Dent"); // Your full name
}
else
{
Console.WriteLine("Try re-running this application with the --help option");
}
}
}
Test your understanding of what you have learned so far by completing the following.
Copy the following questions into your docs\ReadMe.md
file along with your observations of how your program currently works.
dotnet run
in the terminal?dotnet run --help
and dotnet run -- --help
?
--
in the command?dotnet run -- --author
?
dotnet run --author
? Why or why not?dotnet run -- --version
in the terminal?
dotnet run --version
? Why or why not?dotnet run bob
in the terminal? Is it what you expected would happen?There is some background information to your application that is detailed in your .csproj
file (see NaitCli.csproj). This file is critical to your application because it tells the compiler important information to use when generating your executable (.exe
) program.
Modify your program by adding a <Version>0.1.0</Version>
tag in its <PropertyGroup>
tag. Your final contents should match the following (ignoring any version difference in the included "System.CommandLine" package reference).
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<Version>0.1.0</Version>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="System.CommandLine" Version="2.0.0-beta4.22272.1" />
</ItemGroup>
</Project>
Now, re-run your application in the terminal by typing dotnet run -- --version
. Note the difference output than what you got before this change. Make some notes in your docs\ReadMe.md
to describe what you have done.
I'm loving the System.CommandLine package, and I've teaching it for the first time in my Programming Fundamentals class (post-secondary). Thank You!
I'm building up a good tutorial for absolute beginners to use. Here's a PDF of one of my documents that I thought I would share with you (and the community).
Specs-Day-3.pdf
p.s. - If you like my work and think it can be helpful on Microsoft Learn or some other place, I'm quite happy to share. Just let me know what you would need for me to contribute. Thanks again!