Skip to content

Commit a36a957

Browse files
committed
Make a README for the core package
1 parent 8348c0d commit a36a957

File tree

2 files changed

+229
-0
lines changed

2 files changed

+229
-0
lines changed

src/System.CommandLine/README.md

Lines changed: 227 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,227 @@
1+
# System.CommandLine
2+
3+
System.CommandLine provides robust support for command-line parsing, invocation, and shell completions in .NET applications. It supports both POSIX and Windows conventions, making it easy to build professional command-line interfaces.
4+
5+
## Getting Started
6+
7+
### Basic Command
8+
9+
Here's a simple "Hello World" command-line application:
10+
11+
```csharp
12+
using System.CommandLine;
13+
14+
var rootCommand = new RootCommand("Sample command-line app");
15+
16+
var nameOption = new Option<string>(
17+
aliases: ["--name", "-n"],
18+
description: "Your name");
19+
20+
rootCommand.Options.Add(nameOption);
21+
22+
rootCommand.SetAction(parseResult =>
23+
{
24+
string name = parseResult.GetValueForOption(nameOption);
25+
Console.WriteLine($"Hello, {name ?? "World"}!");
26+
});
27+
28+
return await rootCommand.InvokeAsync(args);
29+
```
30+
31+
### Commands with Arguments
32+
33+
Arguments are values passed directly to commands without option names:
34+
35+
```csharp
36+
var fileArgument = new Argument<FileInfo>(
37+
name: "file",
38+
description: "The file to process");
39+
40+
var processCommand = new Command("process", "Process a file");
41+
processCommand.Arguments.Add(fileArgument);
42+
43+
processCommand.SetAction(parseResult =>
44+
{
45+
FileInfo file = parseResult.GetValueForArgument(fileArgument);
46+
Console.WriteLine($"Processing {file.FullName}");
47+
});
48+
49+
rootCommand.Subcommands.Add(processCommand);
50+
```
51+
52+
### Options with Default Values
53+
54+
Options can have default values and validation:
55+
56+
```csharp
57+
var delayOption = new Option<int>(
58+
aliases: ["--delay", "-d"],
59+
getDefaultValue: () => 1000,
60+
description: "Delay in milliseconds");
61+
62+
delayOption.AddValidator(result =>
63+
{
64+
if (result.GetValueOrDefault<int>() < 0)
65+
{
66+
result.ErrorMessage = "Delay must be non-negative";
67+
}
68+
});
69+
70+
rootCommand.Options.Add(delayOption);
71+
```
72+
73+
### Subcommands
74+
75+
Build complex CLI applications with nested commands:
76+
77+
```csharp
78+
var rootCommand = new RootCommand("My application");
79+
80+
var configCommand = new Command("config", "Configure the application");
81+
var configSetCommand = new Command("set", "Set a configuration value");
82+
var configGetCommand = new Command("get", "Get a configuration value");
83+
84+
var keyOption = new Option<string>("--key", "Configuration key");
85+
var valueOption = new Option<string>("--value", "Configuration value");
86+
87+
configSetCommand.Options.Add(keyOption);
88+
configSetCommand.Options.Add(valueOption);
89+
configGetCommand.Options.Add(keyOption);
90+
91+
configCommand.Subcommands.Add(configSetCommand);
92+
configCommand.Subcommands.Add(configGetCommand);
93+
rootCommand.Subcommands.Add(configCommand);
94+
95+
// Usage: myapp config set --key "apiUrl" --value "https://api.example.com"
96+
// Usage: myapp config get --key "apiUrl"
97+
```
98+
99+
### Using Options in Command Handlers
100+
101+
Access option values through the ParseResult:
102+
103+
```csharp
104+
var connectionOption = new Option<string>("--connection", "Database connection string");
105+
var timeoutOption = new Option<int>("--timeout", getDefaultValue: () => 30);
106+
var verboseOption = new Option<bool>("--verbose");
107+
108+
rootCommand.Options.Add(connectionOption);
109+
rootCommand.Options.Add(timeoutOption);
110+
rootCommand.Options.Add(verboseOption);
111+
112+
rootCommand.SetAction(parseResult =>
113+
{
114+
var connection = parseResult.GetValueForOption(connectionOption);
115+
var timeout = parseResult.GetValueForOption(timeoutOption);
116+
var verbose = parseResult.GetValueForOption(verboseOption);
117+
118+
Console.WriteLine($"Connection: {connection}");
119+
Console.WriteLine($"Timeout: {timeout}");
120+
Console.WriteLine($"Verbose: {verbose}");
121+
});
122+
```
123+
124+
### Shell Completions
125+
126+
Enable tab completion for your CLI:
127+
128+
```csharp
129+
// Completions are automatically available for all commands, options, and arguments
130+
var rootCommand = new RootCommand("My app with completions");
131+
132+
var fileOption = new Option<FileInfo>("--file", "The file to process");
133+
fileOption.AddCompletions((ctx) =>
134+
{
135+
// Custom completion logic
136+
return new[] { "file1.txt", "file2.txt", "file3.txt" };
137+
});
138+
139+
rootCommand.Options.Add(fileOption);
140+
141+
// Users can generate completion scripts using dotnet-suggest:
142+
// dotnet tool install -g dotnet-suggest
143+
// dotnet suggest script bash > ~/.bashrc
144+
// dotnet suggest script powershell > $PROFILE
145+
```
146+
147+
### Async Command Handlers
148+
149+
Support for asynchronous operations:
150+
151+
```csharp
152+
var urlOption = new Option<string>("--url", "The URL to fetch");
153+
rootCommand.Options.Add(urlOption);
154+
155+
rootCommand.SetAction(async (parseResult, cancellationToken) =>
156+
{
157+
var url = parseResult.GetValueForOption(urlOption);
158+
if (url != null)
159+
{
160+
using var client = new HttpClient();
161+
var response = await client.GetStringAsync(url, cancellationToken);
162+
Console.WriteLine(response);
163+
}
164+
});
165+
166+
// Or return an exit code:
167+
rootCommand.SetAction(async (parseResult, cancellationToken) =>
168+
{
169+
// Your async logic here
170+
return await Task.FromResult(0); // Return exit code
171+
});
172+
```
173+
174+
## Notable Changes Since v2.0.0-beta7
175+
176+
### New Features
177+
- **Finnish Localization**: Added Finnish language translations for help text and error messages ([#2605](https://github.com/dotnet/command-line-api/pull/2605))
178+
- **Improved Help System**: Enhanced `HelpAction` to allow users to provide custom `MaxWidth` for help text formatting ([#2635](https://github.com/dotnet/command-line-api/pull/2635))
179+
- **Task<int> Support**: Added `SetAction` overload for `Task<int>` return types ([#2634](https://github.com/dotnet/command-line-api/issues/2634))
180+
- **Implicit Arguments**: Added `ArgumentResult.Implicit` property for better argument handling ([#2622](https://github.com/dotnet/command-line-api/issues/2622), [#2625](https://github.com/dotnet/command-line-api/pull/2625))
181+
- **Performance Improvements**: Reduced reflection usage throughout the library for better performance ([#2662](https://github.com/dotnet/command-line-api/pull/2662))
182+
183+
### Bug Fixes
184+
- Fixed issue [#2128](https://github.com/dotnet/command-line-api/issues/2128): Resolved command parsing edge cases ([#2656](https://github.com/dotnet/command-line-api/pull/2656))
185+
- Fixed issue [#2257](https://github.com/dotnet/command-line-api/issues/2257): Corrected argument validation behavior
186+
- Fixed issue [#2589](https://github.com/dotnet/command-line-api/issues/2589): Improved error message clarity ([#2654](https://github.com/dotnet/command-line-api/pull/2654))
187+
- Fixed issue [#2591](https://github.com/dotnet/command-line-api/issues/2591): Resolved option parsing inconsistencies ([#2644](https://github.com/dotnet/command-line-api/pull/2644))
188+
- Fixed issue [#2622](https://github.com/dotnet/command-line-api/issues/2622): Enhanced implicit argument support ([#2625](https://github.com/dotnet/command-line-api/pull/2625))
189+
- Fixed issue [#2628](https://github.com/dotnet/command-line-api/issues/2628): Corrected help text formatting issues
190+
- Fixed issue [#2634](https://github.com/dotnet/command-line-api/issues/2634): Added missing Task<int> action support
191+
- Fixed issue [#2640](https://github.com/dotnet/command-line-api/issues/2640): Resolved completion suggestions for nested commands ([#2646](https://github.com/dotnet/command-line-api/pull/2646))
192+
193+
### Breaking Changes
194+
- Default value handling for `ProcessTerminationTimeout` has been re-added ([#2672](https://github.com/dotnet/command-line-api/pull/2672))
195+
- Some internal APIs have been refactored to reduce reflection usage ([#2662](https://github.com/dotnet/command-line-api/pull/2662))
196+
197+
### Other Improvements
198+
- Updated to .NET 10.0 RC1 compatibility
199+
- Enhanced parsing logic for better POSIX and Windows convention support
200+
- Improved memory usage and performance optimizations
201+
- Better handling of complex command hierarchies
202+
203+
## Documentation
204+
205+
For comprehensive documentation, tutorials, and API reference, visit:
206+
- **[Microsoft Learn Documentation](https://learn.microsoft.com/en-us/dotnet/standard/commandline/)** - Complete guides and API reference
207+
- **[GitHub Repository](https://github.com/dotnet/command-line-api)** - Source code, samples, and issues
208+
- **[Sample Applications](https://github.com/dotnet/command-line-api/tree/main/samples)** - Real-world examples
209+
210+
## Framework Support
211+
212+
- **.NET 8.0+** - Full feature support with trimming and AOT compilation
213+
- **.NET Standard 2.0** - Compatible with .NET Framework 4.6.1+, .NET Core 2.0+
214+
215+
## License
216+
217+
This package is licensed under the [MIT License](https://opensource.org/licenses/MIT).
218+
219+
## Contributing
220+
221+
We welcome contributions! Please see our [Contributing Guide](https://github.com/dotnet/command-line-api/blob/main/CONTRIBUTING.md) for details.
222+
223+
## Support
224+
225+
- **Issues**: [GitHub Issues](https://github.com/dotnet/command-line-api/issues)
226+
- **Discussions**: [GitHub Discussions](https://github.com/dotnet/command-line-api/discussions)
227+
- **Chat**: [Gitter Community](https://gitter.im/dotnet/command-line-api)

src/System.CommandLine/System.CommandLine.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
<Description>Support for parsing command lines, supporting both POSIX and Windows conventions and shell-agnostic command line completions.</Description>
88
<GenerateDocumentationFile>true</GenerateDocumentationFile>
99
<DebugType Condition="'$(Configuration)' == 'Debug'">portable</DebugType>
10+
<PackageReadmeFile>README.md</PackageReadmeFile>
1011
</PropertyGroup>
1112

1213
<PropertyGroup Condition="'$(TargetFramework)' == '$(NetMinimum)'">
@@ -17,6 +18,7 @@
1718

1819
<ItemGroup>
1920
<Compile Include="..\System.Diagnostics.CodeAnalysis.cs" Link="System.Diagnostics.CodeAnalysis\System.Diagnostics.CodeAnalysis.cs" />
21+
<None Include="README.md" Pack="true" PackagePath="/README.md" />
2022
</ItemGroup>
2123

2224
<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">

0 commit comments

Comments
 (0)