Skip to content

Commit 435d44d

Browse files
committed
Remove CommandLineApplication/...Builder from the Quick overview in the readme
1 parent 63b942f commit 435d44d

1 file changed

Lines changed: 112 additions & 111 deletions

File tree

Readme.md

Lines changed: 112 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -110,43 +110,10 @@ Its command-line signature looks like this:
110110
$ ./myapp <value> [--base <base>]
111111
```
112112

113-
To expose your command as an entry point and turn the program into a command-line interface, modify the `Main()` method so that it delegates its execution to an instance of `CommandLineApplication`.
114-
Use the `CommandLineApplicationBuilder` helper to create and configure an application in a series of fluent instructions:
113+
That's all you need — **CliFx** uses source generators to discover commands and produce the `Main()` method automatically, so you don't have to write any boilerplate.
114+
If you wish to customize the application's behavior, you can provide your own `Main()` method as described in the [application configuration](#application-configuration) section.
115115

116-
```csharp
117-
using CliFx;
118-
119-
public static class Program
120-
{
121-
// This Main() method will be generated automatically if you don't implement one yourself
122-
public static async Task<int> Main() =>
123-
await new CommandLineApplicationBuilder()
124-
// Registers all accessible commands from the current assembly
125-
.AddCommandsFromThisAssembly()
126-
// Creates the application instance
127-
.Build()
128-
// Runs the application, resolving command-line arguments and
129-
// environment variables automatically.
130-
.RunAsync();
131-
}
132-
```
133-
134-
> [!TIP]
135-
> If your program does not have a `Main()` method, **CliFx** will generate one for you automatically.
136-
> You only need to implement your own if you wish to customize the configuration of the application.
137-
138-
> [!IMPORTANT]
139-
> Ensure that your `Main()` method returns the integer exit code provided by `CommandLineApplication.RunAsync()`, as shown in the example.
140-
> Exit code is used to communicate execution result to the parent process, so it's important that your program properly propagates it.
141-
142-
> [!NOTE]
143-
> When calling `CommandLineApplication.RunAsync()`, **CliFx** resolves command-line arguments and environment variables from `Environment.GetCommandLineArgs()` and `Environment.GetEnvironmentVariables()` respectively.
144-
> You can also provide them explicitly using one of the other available overloads.
145-
146-
For the command to be available for execution, it needs to be registered with the application.
147-
The above example relies on `AddCommandsFromThisAssembly()` for that, which automatically detects and registers all accessible commands from the current assembly.
148-
149-
Now, the user can execute `LogCommand` by running the application and passing an argument to the `value` parameter:
116+
With the above command defined, the user can execute it by running the application and passing an argument to the `value` parameter:
150117

151118
```console
152119
$ ./myapp 10000
@@ -690,63 +657,6 @@ These rules also make the order of arguments important — the command-line stri
690657
$ ./myapp [command] [...parameters] [...options]
691658
```
692659

693-
### Command instantiation
694-
695-
Because **CliFx** takes responsibility for the application's entire lifecycle, it needs to be capable of instantiating commands at run time.
696-
To facilitate that, it uses an interface called `ITypeInstantiator` that determines how to create a new instance of a given type.
697-
698-
The default implementation of `ITypeInstantiator` only supports types that have public parameter-less constructors, which is sufficient for most common scenarios.
699-
However, in some cases you may want to define a custom instantiator, for example when integrating with an external dependency container.
700-
701-
To do that, pass a custom `ITypeInstantiator` or a factory delegate to the `UseTypeInstantiator(...)` method when building the application:
702-
703-
```csharp
704-
public static class Program
705-
{
706-
public static async Task<int> Main() =>
707-
await new CommandLineApplicationBuilder()
708-
.AddCommandsFromThisAssembly()
709-
.UseTypeInstantiator(type =>
710-
{
711-
var instance = MyTypeFactory.Create(type);
712-
return instance;
713-
})
714-
.Build()
715-
.RunAsync();
716-
}
717-
```
718-
719-
This method also supports `IServiceProvider` through various overloads, which allows you to directly integrate dependency containers that implement this interface.
720-
For example, this is how to configure your application to use [`Microsoft.Extensions.DependencyInjection`](https://nuget.org/packages/Microsoft.Extensions.DependencyInjection) as the type instantiator in **CliFx**:
721-
722-
```csharp
723-
public static class Program
724-
{
725-
public static async Task<int> Main() =>
726-
await new CommandLineApplicationBuilder()
727-
.AddCommandsFromThisAssembly()
728-
.UseTypeInstantiator(commands =>
729-
{
730-
var services = new ServiceCollection();
731-
732-
// Register services
733-
services.AddSingleton<MyService>();
734-
735-
// Register commands
736-
foreach (var command in commands)
737-
services.AddTransient(command.Type);
738-
739-
return services.BuildServiceProvider();
740-
})
741-
.Build()
742-
.RunAsync();
743-
}
744-
```
745-
746-
> [!NOTE]
747-
> If you want to use certain advanced features provided by `Microsoft.Extensions.DependencyInjection`, you may need to do a bit of extra work to configure the container properly.
748-
> For example, to leverage support for keyed services, you need to [manually register an implementation of `IKeyedServiceProvider`](https://github.com/Tyrrrz/CliFx/issues/148).
749-
750660
### Command routing
751661

752662
Command-line applications often provide the user with more than just a single command, facilitating a variety of different workflows.
@@ -836,7 +746,7 @@ You can run `myapp cmd1 [command] --help` to show help for a specific command.
836746
> Defining the default (unnamed) command is not required.
837747
> If it's absent, **CliFx** will generate one for you automatically.
838748
839-
### Reporting errors
749+
### Error reporting
840750

841751
Commands in **CliFx** do not directly return exit codes, but instead communicate execution errors via `CommandException`.
842752
This special exception type can be used to print an error message to the console, return a specific exit code, and also optionally show help text for the current command:
@@ -1001,19 +911,110 @@ public async Task ConcatCommand_executes_successfully()
1001911
}
1002912
```
1003913

1004-
### Debug and preview mode
914+
### Application configuration
915+
916+
By default, **CliFx** source-generates a `Main()` method that builds and runs the application with standard settings.
917+
If you need to customize this behavior, provide your own `Main()` method and use `CommandLineApplicationBuilder` to configure the application:
918+
919+
```csharp
920+
using CliFx;
921+
922+
public static class Program
923+
{
924+
public static async Task<int> Main() =>
925+
await new CommandLineApplicationBuilder()
926+
.AddCommandsFromThisAssembly()
927+
.SetTitle("My App")
928+
.SetVersion("1.0.0")
929+
.Build()
930+
.RunAsync();
931+
}
932+
```
933+
934+
> [!IMPORTANT]
935+
> Ensure that your `Main()` method returns the integer exit code provided by `CommandLineApplication.RunAsync()`, as shown in the example.
936+
> Exit code is used to communicate execution result to the parent process, so it's important that your program properly propagates it.
937+
938+
By default, `CommandLineApplication.RunAsync()` resolves command-line arguments and environment variables from `Environment.GetCommandLineArgs()` and `Environment.GetEnvironmentVariables()` respectively, but you can also provide them explicitly using one of the other available overloads.
939+
940+
The following configuration methods are available on `CommandLineApplicationBuilder`:
941+
942+
- `AddCommand(...)` / `AddCommands(...)` — registers one or more commands with the application. Alternatively, `AddCommandsFromThisAssembly()` detects and registers all accessible commands from the current assembly.
943+
- `SetTitle(...)` — sets the application title displayed in the help text. Defaults to the assembly name.
944+
- `SetExecutableName(...)` — sets the executable name displayed in the help text. Defaults to the assembly file name.
945+
- `SetVersion(...)` — sets the version displayed in the help text and when version info is requested. Defaults to the assembly version.
946+
- `SetDescription(...)` — sets the application description displayed in the help text.
947+
- `UseConsole(...)` — provides a custom `IConsole` implementation, useful for [testing](#testing).
948+
- `UseTypeInstantiator(...)` — provides a custom type instantiator for creating command instances. See [dependency injection](#dependency-injection).
949+
- `AllowDebugMode(...)` / `AllowPreviewMode(...)` — enables diagnostic modes. See [debug and preview mode](#debug-and-preview-mode).
950+
951+
#### Dependency injection
952+
953+
Because **CliFx** takes responsibility for the application's entire lifecycle, it needs to be capable of instantiating commands at run time.
954+
By default, only types with public parameter-less constructors are supported, which is sufficient for most common scenarios.
955+
956+
When integrating with an external dependency container, pass a custom `ITypeInstantiator` or a factory delegate to `UseTypeInstantiator(...)`:
957+
958+
```csharp
959+
public static class Program
960+
{
961+
public static async Task<int> Main() =>
962+
await new CommandLineApplicationBuilder()
963+
.AddCommandsFromThisAssembly()
964+
.UseTypeInstantiator(type =>
965+
{
966+
var instance = MyTypeFactory.Create(type);
967+
return instance;
968+
})
969+
.Build()
970+
.RunAsync();
971+
}
972+
```
973+
974+
This method also supports `IServiceProvider` through various overloads, which allows you to directly integrate dependency containers that implement this interface.
975+
For example, this is how to configure your application to use [`Microsoft.Extensions.DependencyInjection`](https://nuget.org/packages/Microsoft.Extensions.DependencyInjection) as the type instantiator in **CliFx**:
976+
977+
```csharp
978+
public static class Program
979+
{
980+
public static async Task<int> Main() =>
981+
await new CommandLineApplicationBuilder()
982+
.AddCommandsFromThisAssembly()
983+
.UseTypeInstantiator(commands =>
984+
{
985+
var services = new ServiceCollection();
986+
987+
// Register services
988+
services.AddSingleton<MyService>();
989+
990+
// Register commands
991+
foreach (var command in commands)
992+
services.AddTransient(command.Type);
993+
994+
return services.BuildServiceProvider();
995+
})
996+
.Build()
997+
.RunAsync();
998+
}
999+
```
1000+
1001+
> [!NOTE]
1002+
> If you want to use certain advanced features provided by `Microsoft.Extensions.DependencyInjection`, you may need to do a bit of extra work to configure the container properly.
1003+
> For example, to leverage support for keyed services, you need to [manually register an implementation of `IKeyedServiceProvider`](https://github.com/Tyrrrz/CliFx/issues/148).
1004+
1005+
#### Debug and preview mode
10051006

10061007
When troubleshooting issues, you may find it useful to run your application in debug or preview mode.
1007-
These modes are activated through environment variables, which you can configure using `AllowDebugMode(...)` and `AllowPreviewMode(...)` methods on `CommandLineApplicationBuilder`:
1008+
These modes are activated through environment variables, configured using `AllowDebugMode(...)` and `AllowPreviewMode(...)`:
10081009

10091010
```csharp
1010-
var application = new CommandLineApplicationBuilder()
1011-
.AddCommandsFromThisAssembly()
1012-
// Enable debug mode via the CLIFX_DEBUG environment variable
1013-
.AllowDebugMode("CLIFX_DEBUG")
1014-
// Enable preview mode via the CLIFX_PREVIEW environment variable
1015-
.AllowPreviewMode("CLIFX_PREVIEW")
1016-
.Build();
1011+
public static async Task<int> Main() =>
1012+
await new CommandLineApplicationBuilder()
1013+
.AddCommandsFromThisAssembly()
1014+
.AllowDebugMode("CLIFX_DEBUG")
1015+
.AllowPreviewMode("CLIFX_PREVIEW")
1016+
.Build()
1017+
.RunAsync();
10171018
```
10181019

10191020
> [!TIP]
@@ -1035,16 +1036,16 @@ $ CLIFX_PREVIEW=true ./myapp cmd arg1 arg2 -o foo --option bar1 bar2
10351036
cmd <arg1> <arg2> [-o foo] [--option bar1 bar2]
10361037
```
10371038

1038-
To disallow these modes (e.g. for production), simply pass `null` for the corresponding environment variable names:
1039+
Pass `null` to disallow these modes (e.g. for production):
10391040

10401041
```csharp
1041-
var application = new CommandLineApplicationBuilder()
1042-
.AddCommandsFromThisAssembly()
1043-
// Disallow debug mode
1044-
.AllowDebugMode(null)
1045-
// Disallow preview mode
1046-
.AllowPreviewMode(null)
1047-
.Build();
1042+
public static async Task<int> Main() =>
1043+
await new CommandLineApplicationBuilder()
1044+
.AddCommandsFromThisAssembly()
1045+
.AllowDebugMode(null)
1046+
.AllowPreviewMode(null)
1047+
.Build()
1048+
.RunAsync();
10481049
```
10491050

10501051
## Etymology

0 commit comments

Comments
 (0)