### Basic Console Application Setup with ConsoleAppFramework Source: https://github.com/cysharp/consoleappframework/blob/master/ReadMe.md This snippet shows the minimal setup for a console application using ConsoleAppFramework. It demonstrates how to run a simple command defined by a lambda expression, taking a string argument and printing a greeting. ```C# using ConsoleAppFramework; ConsoleApp.Run(args, (string name) => Console.WriteLine($"Hello {name}")); ``` -------------------------------- ### Basic Command Execution (C#) Source: https://github.com/cysharp/consoleappframework/blob/master/ReadMe.md A simple example of running a console application with a single command that takes a string argument. It also shows the generated help text. ```csharp ConsoleApp.Run(args, (string message) => Console.Write($"Hello, {message}")); ``` ```text Usage: [options...] [-h|--help] [--version] Options: --message [Required] ``` -------------------------------- ### Integrating with Microsoft.Extensions.Hosting in C# Source: https://github.com/cysharp/consoleappframework/blob/master/ReadMe.md Demonstrates how to leverage an existing IHostBuilder or HostApplicationBuilder to configure ConsoleAppFramework, enabling the use of common DI and configuration setups across different application types. ```csharp // dotnet add package Microsoft.Extensions.Hosting var app = Host.CreateApplicationBuilder() .ToConsoleAppBuilder(); ``` -------------------------------- ### Configuring Logging with ZLogger in C# Source: https://github.com/cysharp/consoleappframework/blob/master/ReadMe.md Illustrates how to configure logging for ConsoleAppFramework using Microsoft.Extensions.Logging and ZLogger. This example sets up console and file logging with a minimum trace level and shows how to inject ILogger into a command class constructor. ```csharp // Package Import: ZLogger var app = ConsoleApp.Create() .ConfigureLogging(x => { x.ClearProviders(); x.SetMinimumLevel(LogLevel.Trace); x.AddZLoggerConsole(); x.AddZLoggerFile("log.txt"); }); app.Add(); app.Run(args); // inject logger to constructor public class MyCommand(ILogger logger) { public void Echo(string msg) { logger.ZLogInformation($"Message is {msg}"); } } ``` -------------------------------- ### Running Console Application with a Method Reference Source: https://github.com/cysharp/consoleappframework/blob/master/ReadMe.md Illustrates how to use ConsoleAppFramework to run a console application by referencing a separate method. This example shows passing command-line arguments to a `Sum` method that takes two integers. ```C# ConsoleApp.Run(args, Sum); void Sum(int x, int y) => Console.Write(x + y); ``` -------------------------------- ### Generate and Serialize CLI Schema for ConsoleAppFramework Source: https://github.com/cysharp/consoleappframework/blob/master/ReadMe.md Provides instructions on how to install the CLI schema package, retrieve command definitions, and serialize them to JSON for documentation or AI integration. ```bash dotnet add package ConsoleAppFramework.CliSchema ``` ```csharp var app = ConsoleApp.Create(); app.Add("foo", (int x, int y) => { }); CommandHelpDefinition[] schema = app.GetCliSchema(); var json = JsonSerializer.Serialize(schema, CliSchemaJsonSerializerContext.Default.CommandHelpDefinitionArray); var schema2 = JsonSerializer.Deserialize(json, CliSchemaJsonSerializerContext.Default.CommandHelpDefinitionArray); ``` -------------------------------- ### Create Execution Time Logging Filter Source: https://github.com/cysharp/consoleappframework/blob/master/ReadMe.md An example of a filter that measures and logs the execution time of a command, demonstrating how to wrap the Next.InvokeAsync call with timing logic. ```csharp internal class LogRunningTimeFilter(ConsoleAppFilter next) : ConsoleAppFilter(next) { public override async Task InvokeAsync(ConsoleAppContext context, CancellationToken cancellationToken) { var startTime = Stopwatch.GetTimestamp(); ConsoleApp.Log($"Execute command at {DateTime.UtcNow.ToLocalTime()}"); try { await Next.InvokeAsync(context, cancellationToken); ConsoleApp.Log($"Command execute successfully at {DateTime.UtcNow.ToLocalTime()}, Elapsed: " + (Stopwatch.GetElapsedTime(startTime))); } catch { ConsoleApp.Log($"Command execute failed at {DateTime.UtcNow.ToLocalTime()}, Elapsed: " + (Stopwatch.GetElapsedTime(startTime))); throw; } } } ``` -------------------------------- ### Argument Parsing with [Argument] Attribute in C# Source: https://github.com/cysharp/consoleappframework/blob/master/ReadMe.md Demonstrates how to use the [Argument] attribute to define parameters that receive values in order without explicit parameter names. It shows examples for both positional arguments and handling multiple string arguments with params. ```csharp // cmd.exe "input.txt" "output.txt" ConsoleApp.Run(args, ([Argument]string input, [Argument]string output, bool dryRun) => { }); ``` ```csharp // cmd.exe --message "foo bar baz" "output1.txt" "output2.txt" "output3.txt" ConsoleApp.Run(args, (string message, [Argument]params string[] outputs) => { }); ``` -------------------------------- ### Configure Parameter Aliases and Documentation Source: https://context7.com/cysharp/consoleappframework/llms.txt Explains how to use XML documentation tags to provide parameter descriptions and define short-form aliases for command-line arguments. ```csharp using ConsoleAppFramework; var app = ConsoleApp.Create(); app.Add(); app.Run(args); public class FileCommands { /// -i|--input, The input file path. /// -o|--output, The output file path. /// -v, Enable verbose output. /// -n|--dry-run, Perform a dry run without changes. [Command("")] public void Process(string inputFile, string outputFile, bool verbose = false, bool dryRun = false) { if (verbose) Console.WriteLine($"Processing {inputFile} -> {outputFile}"); if (!dryRun) Console.WriteLine("Executing..."); } } ``` -------------------------------- ### Class-Based Command Registration with Add Source: https://context7.com/cysharp/consoleappframework/llms.txt Shows how to register multiple commands efficiently by using a class where public instance methods are automatically recognized as commands. This method supports command descriptions and aliases through XML documentation comments and attributes. ```csharp using ConsoleAppFramework; var app = ConsoleApp.Create(); app.Add(); app.Run(args); public class MyCommands { /// Root command test. /// -m, Message to show. [Command("")] public void Root(string msg) => Console.WriteLine(msg); /// Display message. /// Message to show. public void Echo(string msg) => Console.WriteLine(msg); /// Sum parameters. /// left value. /// right value. public void Sum(int x, int y) => Console.WriteLine(x + y); } // Usage: app -m "hello" (root command) // Usage: app echo --msg "hello" // Usage: app sum --x 10 --y 20 // Help output: // Usage: [command] [options...] [-h|--help] [--version] // // Root command test. // // Options: // -m, --msg Message to show. [Required] // // Commands: // echo Display message. // sum Sum parameters. ``` -------------------------------- ### Registering Commands with ConsoleAppFramework Source: https://github.com/cysharp/consoleappframework/blob/master/ReadMe.md Demonstrates how to register multiple commands with different signatures using the Add method. The framework uses these registrations to generate optimized routing logic at compile time. ```csharp app.Add("foo", () => { }); app.Add("foo bar", (int x, int y) => { }); app.Add("foo bar barbaz", (DateTime dateTime) => { }); app.Add("foo baz", async (string foo = "test", CancellationToken cancellationToken = default) => { }); ``` -------------------------------- ### Implement Graceful Shutdown with CancellationToken Source: https://context7.com/cysharp/consoleappframework/llms.txt Demonstrates how to handle termination signals like Ctrl+C by injecting a CancellationToken into command methods. It also shows how to configure global timeouts for application shutdown. ```csharp using ConsoleAppFramework; await ConsoleApp.RunAsync(args, async (string url, CancellationToken cancellationToken) => { using var client = new HttpClient(); try { for (int i = 0; i < 10; i++) { await Task.Delay(1000, cancellationToken); } } catch (OperationCanceledException) { Console.WriteLine("Operation was cancelled gracefully"); } }); ConsoleApp.Timeout = TimeSpan.FromSeconds(10); ``` -------------------------------- ### Integrating Dependency Injection Source: https://context7.com/cysharp/consoleappframework/llms.txt Illustrates how to integrate Microsoft.Extensions.DependencyInjection to inject services into command classes, lambda parameters, and filters. ```csharp using ConsoleAppFramework; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; var app = ConsoleApp.Create() .ConfigureServices(services => { services.AddSingleton(); services.AddTransient(); }) .ConfigureLogging(logging => { logging.AddConsole(); logging.SetMinimumLevel(LogLevel.Debug); }); app.Add(); app.Run(args); public class MyCommands(ILogger logger, IMyService service) { public void Process(string input) { logger.LogInformation("Processing: {Input}", input); service.DoWork(input); } } app.Add("quick", ([FromServices] IMyService service, string data) => { service.DoWork(data); }); internal class ServiceFilter(ILogger logger, ConsoleAppFilter next) : ConsoleAppFilter(next) { public override async Task InvokeAsync(ConsoleAppContext context, CancellationToken cancellationToken) { logger.LogDebug("Filter executing"); await Next.InvokeAsync(context, cancellationToken); } } public interface IMyService { void DoWork(string data); } public class MyService : IMyService { public void DoWork(string data) => Console.WriteLine($"Working on: {data}"); } public interface IRepository { } public class Repository : IRepository { } ``` -------------------------------- ### Type Conversion for Command-Line Arguments in C# Source: https://github.com/cysharp/consoleappframework/blob/master/ReadMe.md Explains how ConsoleAppFramework handles type conversion for command-line arguments. It covers basic primitive types using TryParse, ISpanParsable for more complex types like DateTime and Guid, and Enum.TryParse for enumerations. Boolean arguments are treated as flags. ```csharp // Basic primitive types use TryParse // ISpanParsable types like DateTime, Guid use TryParse // Enums use Enum.TryParse(ignoreCase: true) // bool is a flag, becomes true when present ``` -------------------------------- ### Simple Command Execution with ConsoleApp.Run Source: https://context7.com/cysharp/consoleappframework/llms.txt Demonstrates the basic usage of ConsoleApp.Run for executing single commands using lambda expressions or method references. It covers synchronous and asynchronous execution, handling of CancellationToken for graceful shutdown, and setting exit codes. ```csharp using ConsoleAppFramework; // Basic usage with lambda - creates command: app --foo 10 --bar 20 ConsoleApp.Run(args, (int foo, int bar) => Console.WriteLine($"Sum: {foo + bar}")); // Using a method reference ConsoleApp.Run(args, Sum); void Sum(int x, int y) => Console.WriteLine($"Sum: {x + y}"); // Async execution with CancellationToken for graceful shutdown (Ctrl+C handling) await ConsoleApp.RunAsync(args, async (string url, CancellationToken cancellationToken) => { using var client = new HttpClient(); var content = await client.GetStringAsync(url, cancellationToken); Console.WriteLine(content); }); // Return int to set exit code ConsoleApp.Run(args, int (int value) => value > 0 ? 0 : 1); // Return Task for async exit code await ConsoleApp.RunAsync(args, async Task (string url, CancellationToken ct) => { using var client = new HttpClient(); var response = await client.GetAsync(url, ct); return (int)response.StatusCode; }); ``` -------------------------------- ### Initialize ConsoleAppBuilder in v5 Source: https://github.com/cysharp/consoleappframework/blob/master/ReadMe.md Demonstrates the updated initialization pattern for ConsoleAppBuilder in version 5, which now integrates with the .NET Host ApplicationBuilder. ```csharp var app = Host.CreateApplicationBuilder() .ToConsoleAppBuilder(); ``` -------------------------------- ### Registering Multiple Commands from a Class in C# Source: https://github.com/cysharp/consoleappframework/blob/master/ReadMe.md Demonstrates how to add multiple commands at once by using a class where public methods are treated as commands. This approach supports document comments and constructor injection for cleaner code. ```csharp var app = ConsoleApp.Create(); app.Add(); app.Run(args); public class MyCommands { /// Root command test. /// -m, Message to show. [Command("")] public void Root(string msg) => Console.WriteLine(msg); /// Display message. /// Message to show. public void Echo(string msg) => Console.WriteLine(msg); /// Sum parameters. /// left value. /// right value. public void Sum(int x, int y) => Console.WriteLine(x + y); } ``` -------------------------------- ### Configuring Global Options Source: https://context7.com/cysharp/consoleappframework/llms.txt Shows how to define options that apply across all commands using ConfigureGlobalOptions. This allows for shared configuration like logging levels or dry-run flags. ```csharp using ConsoleAppFramework; var app = ConsoleApp.Create(); app.ConfigureGlobalOptions((ref ConsoleApp.GlobalOptionsBuilder builder) => { var dryRun = builder.AddGlobalOption("--dry-run", "Perform a dry run"); var verbose = builder.AddGlobalOption("-v|--verbose", "Enable verbose output"); var config = builder.AddGlobalOption("--config", "Config file path", "appsettings.json"); var logLevel = builder.AddRequiredGlobalOption("--log-level", "Logging level"); return new GlobalOptions(dryRun, verbose, config, logLevel); }); app.Add("deploy", (string environment, ConsoleAppContext context) => { var opts = (GlobalOptions)context.GlobalOptions!; if (opts.Verbose) Console.WriteLine("Verbose mode enabled"); if (opts.DryRun) Console.WriteLine("[DRY RUN]"); Console.WriteLine($"Config: {opts.Config}"); Console.WriteLine($"Log Level: {opts.LogLevel}"); Console.WriteLine($"Deploying to {environment}..."); }); app.Run(args); public enum LogLevel { Debug, Info, Warning, Error } record GlobalOptions(bool DryRun, bool Verbose, string Config, LogLevel LogLevel); ``` -------------------------------- ### Initialize OpenTelemetry Tracing and Metrics Source: https://github.com/cysharp/consoleappframework/blob/master/ReadMe.md Configures the HostApplicationBuilder to export telemetry data to an OTLP endpoint, enabling metrics and tracing for the console application. ```csharp Environment.SetEnvironmentVariable("OTEL_EXPORTER_OTLP_ENDPOINT", "http://localhost:4317"); var builder = Host.CreateApplicationBuilder(args); builder.Logging.AddOpenTelemetry(logging => { logging.IncludeFormattedMessage = true; logging.IncludeScopes = true; }); builder.Services.AddOpenTelemetry() .UseOtlpExporter() .ConfigureResource(resource => { resource.AddService("ConsoleAppFramework Telemetry Sample"); }) .WithMetrics(metrics => { metrics.AddRuntimeInstrumentation() .AddHttpClientInstrumentation(); }) .WithTracing(tracing => { tracing.SetSampler(new AlwaysOnSampler()) .AddHttpClientInstrumentation() .AddSource(ConsoleAppFrameworkSampleActivitySource.Name); }); var app = builder.ToConsoleAppBuilder(); app.Add(); ``` -------------------------------- ### Integrate .NET Generic Host with ConsoleAppFramework Source: https://context7.com/cysharp/consoleappframework/llms.txt This C# code snippet demonstrates how to integrate ConsoleAppFramework with the .NET Generic Host. It sets up the application builder using `Host.CreateApplicationBuilder` and converts it to a `ConsoleAppBuilder` using `ToConsoleAppBuilder`. It then adds a command class `MyCommands` which utilizes `ILogger` and `IConfiguration` services provided by the host. Finally, it runs the application. ```csharp using ConsoleAppFramework; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Configuration; var app = Host.CreateApplicationBuilder(args) .ToConsoleAppBuilder(); // All Host services are available app.Add(); await app.RunAsync(args); public class MyCommands(ILogger logger, IConfiguration config) { public void Run() { var setting = config["MySetting"]; logger.LogInformation("Running with setting: {Setting}", setting); } } ``` -------------------------------- ### Run Async Lambda with CancellationToken (C#) Source: https://github.com/cysharp/consoleappframework/blob/master/ReadMe.md Shows how to execute an asynchronous command using a lambda expression with ConsoleApp.RunAsync. It includes handling a CancellationToken for graceful shutdown and demonstrating task delays. ```csharp // --foo, --bar await ConsoleApp.RunAsync(args, async (int foo, int bar, CancellationToken cancellationToken) => { await Task.Delay(TimeSpan.FromSeconds(5), cancellationToken); Console.WriteLine($"Sum: {foo + bar}"); }); ``` -------------------------------- ### Multiple Commands and Configuration with ConsoleAppBuilder Source: https://context7.com/cysharp/consoleappframework/llms.txt Illustrates how to use ConsoleAppBuilder to create a CLI application with multiple commands, including a root command. This approach allows for registering commands by name and supports asynchronous commands with return values for exit codes. ```csharp using ConsoleAppFramework; var app = ConsoleApp.Create(); // Register root command (empty string) app.Add("", (string msg) => Console.WriteLine(msg)); // Register named commands app.Add("echo", (string msg) => Console.WriteLine(msg)); app.Add("sum", (int x, int y) => Console.WriteLine(x + y)); // Register async command with return value app.Add("fetch", async Task (string url, CancellationToken ct) => { using var client = new HttpClient(); var response = await client.GetAsync(url, ct); return (int)response.StatusCode; }); // Run the application // Usage: app --msg "hello" (root command) // Usage: app echo --msg "hello" // Usage: app sum --x 10 --y 20 app.Run(args); ``` -------------------------------- ### Configure Nested Command Hierarchies Source: https://context7.com/cysharp/consoleappframework/llms.txt Demonstrates how to create deep command structures using space-separated paths or by registering classes at specific nested levels within the ConsoleAppFramework. ```csharp using ConsoleAppFramework; var app = ConsoleApp.Create(); app.Add("db", () => Console.WriteLine("db root")); app.Add("db migrate", () => Console.WriteLine("db migrate")); app.Add("db migrate up", (int steps) => Console.WriteLine($"Migrating up {steps} steps")); app.Add("db migrate down", (int steps) => Console.WriteLine($"Migrating down {steps} steps")); app.Add("db seed", () => Console.WriteLine("Seeding database")); app.Add("storage"); app.Run(args); public class StorageCommands { public void List() => Console.WriteLine("Listing storage"); public void Upload(string file) => Console.WriteLine($"Uploading {file}"); public void Download(string file) => Console.WriteLine($"Downloading {file}"); } ``` -------------------------------- ### Configure Global Options in C# Source: https://github.com/cysharp/consoleappframework/blob/master/ReadMe.md Demonstrates how to define and retrieve global options for all commands in a ConsoleAppFramework application. It shows how to add optional and required global options and how parsed values are stored in ConsoleAppContext.GlobalOptions. ```csharp var app = ConsoleApp.Create(); // builder: Func app.ConfigureGlobalOptions((ref builder) => { var dryRun = builder.AddGlobalOption("--dry-run"); var verbose = builder.AddGlobalOption("-v|--verbose"); var intParameter = builder.AddRequiredGlobalOption("--int-parameter", "integer parameter"); // return value stored to ConsoleAppContext.GlobalOptions return new GlobalOptions(dryRun, verbose, intParameter); }); app.Add("", (int x, int y, ConsoleAppContext context) => { var globalOptions = (GlobalOptions)context.GlobalOptions; Console.WriteLine(globalOptions + ":" + (x, y)); }); app.Run(args); internal record GlobalOptions(bool DryRun, bool Verbose, int IntParameter); ``` ```csharp var app = ConsoleApp.Create(); // builder: Func app.ConfigureGlobalOptions((ref builder) => { var dryRun = builder.AddGlobalOption("--dry-run"); var verbose = builder.AddGlobalOption("-v|--verbose"); var intParameter = builder.AddRequiredGlobalOption("--int-parameter", "integer parameter"); // return value stored to ConsoleAppContext.GlobalOptions return new GlobalOptions(dryRun, verbose, intParameter); }); app.ConfigureServices((context, configuration, services) => { // store global-options to DI var globalOptions = (GlobalOptions)context.GlobalOptions; services.AddSingleton(globalOptions); // check global-options value to configure services services.AddLogging(logging => { if (globalOptions.Verbose) { logging.SetMinimumLevel(LogLevel.Trace); } }); }); app.Add(); app.Run(args); internal record GlobalOptions(bool DryRun, bool Verbose, int IntParameter); // get GlobalOptions from DI internal class Commands(GlobalOptions globalOptions) { [Command("cmd-a")] public void CommandA(int x, int y) { Console.WriteLine("A:" + globalOptions + ":" + (x, y)); } [Command("cmd-b")] public void CommandB(int x, int y) { Console.WriteLine("B:" + globalOptions + ":" + (x, y)); } } ``` -------------------------------- ### Implementing Graceful Shutdown with CancellationToken Source: https://github.com/cysharp/consoleappframework/blob/master/ReadMe.md Shows how to use CancellationToken to handle Ctrl+C signals or custom key triggers to perform a clean shutdown of an application task. ```csharp var cts = new CancellationTokenSource(); _ = Task.Run(() => { while (Console.ReadKey().Key != ConsoleKey.Q) ; Console.WriteLine(); cts.Cancel(); }); var app = ConsoleApp.Create(); app.Add("", async (CancellationToken cancellationToken) => { try { for (int i = 0; i < 10; i++) { Console.WriteLine($"Running main task iteration {i + 1}/10. Press 'Q' to quit."); await Task.Delay(TimeSpan.FromSeconds(1), cancellationToken); } } catch (OperationCanceledException) { Console.WriteLine("Main task was cancelled."); } }); await app.RunAsync(args, cts.Token); ``` -------------------------------- ### Implement Middleware with ConsoleAppFilter Source: https://context7.com/cysharp/consoleappframework/llms.txt Demonstrates how to create and register filters to intercept command execution for logging, timing, and error handling. ```csharp using ConsoleAppFramework; using System.Diagnostics; var app = ConsoleApp.Create(); app.UseFilter(); app.UseFilter(); app.Add(); app.Run(args); internal class LoggingFilter(ConsoleAppFilter next) : ConsoleAppFilter(next) { public override async Task InvokeAsync(ConsoleAppContext context, CancellationToken cancellationToken) { Console.WriteLine($"[LOG] Executing command: {context.CommandName}"); await Next.InvokeAsync(context, cancellationToken); } } [ConsoleAppFilter] public class MyCommands { [ConsoleAppFilter] public void Process() => Console.WriteLine("Processing..."); } ``` -------------------------------- ### Registering Multiple Commands with ConsoleAppBuilder (C#) Source: https://github.com/cysharp/consoleappframework/blob/master/ReadMe.md Shows how to use ConsoleAppBuilder to register multiple commands, including a root command, and then run the application. This approach is suitable for more complex scenarios. ```csharp var app = ConsoleApp.Create(); app.Add("", (string msg) => Console.WriteLine(msg)); app.Add("echo", (string msg) => Console.WriteLine(msg)); app.Add("sum", (int x, int y) => Console.WriteLine(x + y)); // --msg // echo --msg // sum --x --y app.Run(args); ``` -------------------------------- ### Parameter Binding and Parsing Source: https://github.com/cysharp/consoleappframework/blob/master/ReadMe.md Illustrates how to define command-line arguments using method parameters. The framework supports various types including enums, arrays, nullable types, and C# 12 params arrays. ```csharp ConsoleApp.Run(args, ( [Argument]DateTime dateTime, // Argument [Argument]Guid guidvalue, // int intVar, // required bool boolFlag, // flag MyEnum enumValue, // enum int[] array, // array MyClass obj, // object string optional = "abcde", // optional double? nullableValue = null, // nullable params string[] paramsArray // params ) => { }); ``` -------------------------------- ### ConsoleAppFramework Basic Usage Source: https://github.com/cysharp/consoleappframework/blob/master/ReadMe.md Demonstrates the basic usage of ConsoleAppFramework to run a simple command-line application. ```APIDOC ## ConsoleApp.Run Basic Example ### Description This example shows how to use the `ConsoleApp.Run` method to create a simple command-line application that accepts two integer arguments and prints their sum. ### Method `ConsoleApp.Run` ### Endpoint N/A (This is a library usage example, not an HTTP endpoint) ### Parameters This method takes command-line arguments and a delegate (Action or Func) representing the command to execute. ### Request Example ```csharp using ConsoleAppFramework; // Command-line arguments: ./cmd --foo 10 --bar 20 ConsoleApp.Run(args, (int foo, int bar) => Console.WriteLine($"Sum: {foo + bar}")); ``` ### Response This method does not return a value directly but executes the provided command delegate and handles argument parsing and error reporting. ``` -------------------------------- ### Creating Nested Commands in C# Source: https://github.com/cysharp/consoleappframework/blob/master/ReadMe.md Illustrates how to create a deep command hierarchy by registering commands with paths separated by spaces. This allows for organizing commands into logical groups and sub-groups. ```csharp var app = ConsoleApp.Create(); app.Add("foo", () => { }); app.Add("foo bar", () => { }); app.Add("foo bar barbaz", () => { }); app.Add("foo baz", () => { }); // Commands: // foo // foo bar // foo bar barbaz // foo baz app.Run(args); ``` ```csharp var app = ConsoleApp.Create(); app.Add("foo"); // Commands: // foo Root command test. // foo echo Display message. // foo sum Sum parameters. app.Run(args); ``` -------------------------------- ### Help Display Generation in ConsoleAppFramework Source: https://github.com/cysharp/consoleappframework/blob/master/ReadMe.md Demonstrates the generation of help text for console applications using ConsoleAppFramework. The help information, including usage and options, is embedded as string constants for maximum performance. ```C# static partial void ShowHelp(int helpId) { Log(@"Usage: [options...] [-h|--help] [--version] Options: --foo [Required] --bar [Required] "); } } ``` -------------------------------- ### Run Static Function with Function Pointer (C#) Source: https://github.com/cysharp/consoleappframework/blob/master/ReadMe.md Demonstrates how to pass a static function as a function pointer to ConsoleApp.Run for maximum performance. This requires an unsafe context and a named static function. ```csharp unsafe { ConsoleApp.Run(args, &Sum); } static void Sum(int x, int y) => Console.Write(x + y); ``` ```csharp public static unsafe void Run(string[] args, delegate* managed command) ``` -------------------------------- ### Configure Dependency Injection Containers Source: https://github.com/cysharp/consoleappframework/blob/master/ReadMe.md Demonstrates how to integrate external DI containers such as DryIoc or Autofac into a ConsoleAppFramework application using IServiceProviderFactory. ```csharp .ConfigureContainer(new DryIocServiceProviderFactory(), container => { container.Register(); }); app.Add("", ([FromServices] MyService service) => { }); app.Run(args); ``` ```csharp // dotnet add package Microsoft.Extensions.DependencyInjection // dotnet add package Autofac.Extensions.DependencyInjection var app = ConsoleApp.Create() .ConfigureContainer(new AutofacServiceProviderFactory(), builder => { builder.RegisterType(); }); app.Add("", ([FromServices] MyService service) => { }); app.Run(args); ``` -------------------------------- ### Configuring Logging with ConfigureLogging Source: https://github.com/cysharp/consoleappframework/blob/master/ReadMe.md Customize logging behavior by using `ConfigureLogging` to set minimum levels, add providers (like console or file logging), and integrate with libraries such as ZLogger. ```APIDOC ## Configuring Logging with ConfigureLogging ### Description ConsoleAppFramework allows for flexible logging configuration using the `ConfigureLogging` method. This enables you to set logging levels, add various logging providers (e.g., console, file), and integrate with high-performance logging libraries like ZLogger. ### Method `ConsoleAppBuilder.ConfigureLogging(Action configure) ` ### Endpoint N/A (Configuration method) ### Parameters #### Request Body - **configure** (Action) - A delegate to configure the logging builder. ### Request Example ```csharp // Package Import: ZLogger var app = ConsoleApp.Create() .ConfigureLogging(x => { x.ClearProviders(); x.SetMinimumLevel(LogLevel.Trace); x.AddZLoggerConsole(); x.AddZLoggerFile("log.txt"); }); app.Add(); app.Run(args); // inject logger to constructor public class MyCommand(ILogger logger) { public void Echo(string msg) { logger.ZLogInformation($"Message is {msg}"); } } ``` ### Response N/A ### Response Example N/A ``` -------------------------------- ### Define Command Aliases Source: https://context7.com/cysharp/consoleappframework/llms.txt Shows how to define alternative names for commands using the pipe character in strings or the Command attribute on class methods. ```csharp using ConsoleAppFramework; var app = ConsoleApp.Create(); app.Add("build|b", () => Console.WriteLine("Building...")); app.Add("test|t", () => Console.WriteLine("Testing...")); app.Add(); app.Run(args); public class Commands { [Command("check|c")] public void Check() => Console.WriteLine("Checking..."); [Command("doc|d")] public void Doc() => Console.WriteLine("Documenting..."); } ``` -------------------------------- ### Reading appsettings.json with DI in C# Source: https://github.com/cysharp/consoleappframework/blob/master/ReadMe.md Demonstrates how to configure ConsoleAppFramework to read settings from appsettings.json, bind them to a C# class using IOptions, and inject them into commands. Requires Microsoft.Extensions.Configuration.Json and Microsoft.Extensions.Options.ConfigurationExtensions packages. ```json { "Position": { "Title": "Editor", "Name": "Joe Smith" }, "MyKey": "My appsettings.json Value", "AllowedHosts": "*" } ``` ```xml PreserveNewest ``` ```csharp // Package Import: Microsoft.Extensions.Configuration.Json var app = ConsoleApp.Create() .ConfigureDefaultConfiguration() .ConfigureServices((configuration, services) => { // Package Import: Microsoft.Extensions.Options.ConfigurationExtensions services.Configure(configuration.GetSection("Position")); }); app.Add(); app.Run(args); // inject options public class MyCommand(IOptions options) { public void Echo(string msg) { ConsoleApp.Log($"Binded Option: {options.Value.Title} {options.Value.Name}"); } } public class PositionOptions { public string Title { get; set; } = ""; public string Name { get; set; } = ""; } ``` -------------------------------- ### ConsoleApp.Run - Simple Command Execution Source: https://context7.com/cysharp/consoleappframework/llms.txt Executes a single command using a lambda expression or method reference, with support for async execution and cancellation tokens. ```APIDOC ## ConsoleApp.Run ### Description Executes a simple CLI command. The framework parses arguments based on the provided delegate signature. ### Method N/A (CLI Execution) ### Parameters #### Arguments - **args** (string[]) - Required - The command line arguments passed to the application. - **handler** (Delegate) - Required - The lambda or method reference to execute. ### Request Example // app --foo 10 --bar 20 ConsoleApp.Run(args, (int foo, int bar) => Console.WriteLine($"Sum: {foo + bar}")); ### Response - **Exit Code** (int) - Returns 0 for success, non-zero for failure. ``` -------------------------------- ### Dependency Injection with ConsoleAppFramework in C# Source: https://github.com/cysharp/consoleappframework/blob/master/ReadMe.md Shows how to configure services using Dependency Injection with ConsoleAppFramework. It demonstrates adding transient services and injecting them into command handlers using the [FromServices] attribute or constructor injection. ```csharp var app = ConsoleApp.Create() .ConfigureServices(service => { service.AddTransient(); }); app.Add("", ([FromServices] MyService service, int x, int y) => Console.WriteLine(x + y)); app.Run(args); ``` -------------------------------- ### Registering POSIX Signal Handler for Timeout Source: https://github.com/cysharp/consoleappframework/blob/master/ReadMe.md Demonstrates how to manually register a POSIX signal handler to manage timeouts and cancellation tokens for command execution. ```csharp using var posixSignalHandler = PosixSignalHandler.Register(ConsoleApp.Timeout); var arg0 = posixSignalHandler.Token; await Task.Run(() => command(arg0!)).WaitAsync(posixSignalHandler.TimeoutToken); ``` -------------------------------- ### Required NuGet Packages for Configuration Source: https://github.com/cysharp/consoleappframework/blob/master/ReadMe.md Lists the essential NuGet packages needed to enable JSON configuration reading and options binding within ConsoleAppFramework without a hosting dependency. ```xml ``` -------------------------------- ### Register ConsoleAppFilters Source: https://github.com/cysharp/consoleappframework/blob/master/ReadMe.md Demonstrates how to apply filters globally, at the class level, or at the method level using UseFilter or ConsoleAppFilter attributes. ```csharp var app = ConsoleApp.Create(); app.UseFilter(); app.Add(); app.Run(args); [ConsoleAppFilter] public class MyCommand { [ConsoleAppFilter] public void Echo(string msg) => Console.WriteLine(msg); } ``` -------------------------------- ### Command with Document Comments for Aliases and Descriptions (C#) Source: https://github.com/cysharp/consoleappframework/blob/master/ReadMe.md Illustrates how to use document comments to define command descriptions and parameter aliases, avoiding attribute clutter. This requires a named static method within a class. ```csharp ConsoleApp.Run(args, Commands.Hello); static class Commands { /// /// Display Hello. /// /// -m, Message to show. public static void Hello(string message) => Console.Write($"Hello, {message}"); } ``` ```text Usage: [options...] [-h|--help] [--version] Display Hello. Options: -m, --message Message to show. [Required] ``` -------------------------------- ### Configure OpenTelemetry Dependencies Source: https://github.com/cysharp/consoleappframework/blob/master/ReadMe.md Lists the required NuGet packages for enabling OpenTelemetry instrumentation and exporting in a .NET console application. ```xml ``` -------------------------------- ### Execute Sequential and Parallel HTTP Requests in ConsoleAppFramework Source: https://github.com/cysharp/consoleappframework/blob/master/ReadMe.md Demonstrates how to perform sequential and parallel HTTP requests within a ConsoleAppFramework command. It uses HttpClient to fetch data and Task.WhenAll for parallel execution. ```csharp public class SampleCommand(ILogger logger) { [Command("")] public async Task Run(CancellationToken cancellationToken) { using var httpClient = new HttpClient(); var ms = await httpClient.GetStringAsync("https://www.microsoft.com", cancellationToken); var google = await httpClient.GetStringAsync("https://www.google.com", cancellationToken); logger.LogInformation("Sequential Query done."); var ms2 = httpClient.GetStringAsync("https://www.microsoft.com", cancellationToken); var google2 = httpClient.GetStringAsync("https://www.google.com", cancellationToken); var apple2 = httpClient.GetStringAsync("https://www.apple.com", cancellationToken); await Task.WhenAll(ms2, google2, apple2); logger.LogInformation("Parallel Query done."); } } ``` -------------------------------- ### Customizing Framework Logging Methods in C# Source: https://github.com/cysharp/consoleappframework/blob/master/ReadMe.md Demonstrates how to replace the default framework logging methods (ConsoleApp.Log and ConsoleApp.LogError) with custom implementations, typically using an injected ILogger instance. This allows for consistent logging behavior across the application and framework outputs. ```csharp app.PostConfigureServices((serviceProvider) => { var logger = serviceProvider.GetRequiredService>(); ConsoleApp.Log = msg => logger.LogInformation(msg); ConsoleApp.LogError = msg => logger.LogError(msg); }); ``` -------------------------------- ### Dependency Injection with ConfigureServices Source: https://github.com/cysharp/consoleappframework/blob/master/ReadMe.md ConsoleAppFramework fully supports Dependency Injection. You can configure services using `ConfigureServices` to inject dependencies like loggers, configurations, or custom services into your commands. ```APIDOC ## Dependency Injection with ConfigureServices ### Description ConsoleAppFramework integrates seamlessly with Dependency Injection containers like `Microsoft.Extensions.DependencyInjection`. The `ConfigureServices` method allows you to register services that can then be injected into your commands using attributes like `[FromServices]` or constructor injection. ### Method `ConsoleApp.Create().ConfigureServices(Action configure) ` ### Endpoint N/A (Configuration method) ### Parameters #### Request Body - **configure** (Action) - A delegate to configure the service collection. ### Request Example ```csharp var app = ConsoleApp.Create() .ConfigureServices(service => { service.AddTransient(); }); app.Add("", ([FromServices] MyService service, int x, int y) => Console.WriteLine(x + y)); app.Run(args); ``` ### Response N/A ### Response Example N/A ``` -------------------------------- ### Parameter Default Values and Hidden Attributes (C#) Source: https://github.com/cysharp/consoleappframework/blob/master/ReadMe.md Demonstrates how to set default values for parameters and hide them in help text using attributes. It also shows the generated usage text with default values displayed or omitted. ```csharp ConsoleApp.Run(args, (Fruit myFruit = Fruit.Apple, [HideDefaultValue] Fruit myFruit2 = Fruit.Grape) => { }); enum Fruit { Orange, Grape, Apple } ``` ```text Usage: [options...] [-h|--help] [--version] Options: --my-fruit [Default: Apple] --my-fruit2 ``` -------------------------------- ### Handle Enum Parameters in ConsoleAppFramework Source: https://context7.com/cysharp/consoleappframework/llms.txt Explains how to use enums as command-line arguments, which are parsed case-insensitively and provide automatic validation feedback. ```csharp using ConsoleAppFramework; ConsoleApp.Run(args, (LogLevel logLevel, OutputFormat format = OutputFormat.Text) => { Console.WriteLine($"Log Level: {logLevel}, Format: {format}"); }); public enum LogLevel { Debug, Info, Warning, Error } public enum OutputFormat { Text, Json, Xml } ``` -------------------------------- ### ConsoleApp.Run Source: https://github.com/cysharp/consoleappframework/blob/master/ReadMe.md The entry point for executing a console application using a lambda expression or method reference. ```APIDOC ## POST ConsoleApp.Run ### Description Executes the console application logic. The framework automatically parses command-line arguments based on the provided lambda or method signature. ### Method POST (Conceptual execution) ### Endpoint ConsoleApp.Run(string[] args, Delegate command) ### Parameters #### Request Body - **args** (string[]) - Required - The command-line arguments passed to the application. - **command** (Delegate) - Required - A lambda expression or method reference defining the command logic. ### Request Example ```csharp ConsoleApp.Run(args, (string name) => Console.WriteLine($"Hello {name}")); ``` ### Response #### Success Response (200) - **ExitCode** (int) - Returns 0 on success, or the integer returned by the command method. #### Response Example ```csharp // Execution of: sampletool --name "foo" // Output: Hello foo ``` ``` -------------------------------- ### ConsoleAppBuilder - Multiple Commands Source: https://context7.com/cysharp/consoleappframework/llms.txt Configures complex CLI applications with multiple commands, dependency injection, and middleware filters. ```APIDOC ## ConsoleApp.Create ### Description Initializes a builder to register multiple commands and configure the application pipeline. ### Method N/A (Builder Pattern) ### Parameters #### Methods - **Add(string name, Delegate handler)** - Registers a command by name. - **Run(string[] args)** - Executes the registered application. ### Request Example var app = ConsoleApp.Create(); app.Add("echo", (string msg) => Console.WriteLine(msg)); app.Run(args); ### Response - **Execution** (void/Task) - Executes the matched command logic. ``` -------------------------------- ### Full Generated Run Method Implementation - C# Source: https://github.com/cysharp/consoleappframework/blob/master/ReadMe.md This snippet provides the complete generated source code for the `Run` method within ConsoleAppFramework. It details the argument parsing logic, including handling optional and required arguments, type conversion using `int.TryParse`, and error handling for missing or invalid arguments. ```csharp namespace ConsoleAppFramework; internal static partial class ConsoleApp { public static void Run(string[] args, Action command) { if (TryShowHelpOrVersion(args, 2, -1)) return; var arg0 = default(int); var arg0Parsed = false; var arg1 = default(int); var arg1Parsed = false; try { for (int i = 0; i < args.Length; i++) { var name = args[i]; switch (name) { case "--foo": { if (!TryIncrementIndex(ref i, args.Length) || !int.TryParse(args[i], out arg0)) { ThrowArgumentParseFailed("foo", args[i]); } arg0Parsed = true; break; } case "--bar": { if (!TryIncrementIndex(ref i, args.Length) || !int.TryParse(args[i], out arg1)) { ThrowArgumentParseFailed("bar", args[i]); } arg1Parsed = true; break; } default: if (string.Equals(name, "--foo", StringComparison.OrdinalIgnoreCase)) { if (!TryIncrementIndex(ref i, args.Length) || !int.TryParse(args[i], out arg0)) { ThrowArgumentParseFailed("foo", args[i]); } arg0Parsed = true; break; } if (string.Equals(name, "--bar", StringComparison.OrdinalIgnoreCase)) { if (!TryIncrementIndex(ref i, args.Length) || !int.TryParse(args[i], out arg1)) { ThrowArgumentParseFailed("bar", args[i]); } arg1Parsed = true; break; } ThrowArgumentNameNotFound(name); break; } } if (!arg0Parsed) ThrowRequiredArgumentNotParsed("foo"); if (!arg1Parsed) ThrowRequiredArgumentNotParsed("bar"); command(arg0!, arg1!); } catch (Exception ex) { ``` -------------------------------- ### Configuring Custom DI Container with DryIoc in C# Source: https://github.com/cysharp/consoleappframework/blob/master/ReadMe.md Illustrates how to configure ConsoleAppFramework to use a different DI container, such as DryIoc, by utilizing the ConfigureContainer method and setting an IServiceProviderFactory. Requires Microsoft.Extensions.DependencyInjection and DryIoc.Microsoft.DependencyInjection packages. ```csharp // dotnet add package Microsoft.Extensions.DependencyInjection // dotnet add package DryIoc.Microsoft.DependencyInjection var app = ConsoleApp.Create() // setup DryIoc as the DI container ``` -------------------------------- ### Run Minimal CLI Application - C# Source: https://github.com/cysharp/consoleappframework/blob/master/ReadMe.md This snippet demonstrates the basic usage of ConsoleApp.Run to execute a simple command-line application. It takes command-line arguments and passes them to a lambda expression for processing. The framework handles argument parsing and invocation. ```csharp using ConsoleAppFramework; // args: ./cmd --foo 10 --bar 20 ConsoleApp.Run(args, (int foo, int bar) => Console.WriteLine($"Sum: {foo + bar}")); ``` -------------------------------- ### Accessing Command Context and State Source: https://context7.com/cysharp/consoleappframework/llms.txt Demonstrates how to use ConsoleAppContext to access command metadata, arguments, and pass state between filters. It also shows how to handle escaped arguments using the double-dash syntax. ```csharp using ConsoleAppFramework; var app = ConsoleApp.Create(); app.UseFilter(); app.Add("", (int x, int y, ConsoleAppContext context) => { var state = (AppState)context.State!; Console.WriteLine($"Request ID: {state.RequestId}"); Console.WriteLine($"User: {state.UserId}"); Console.WriteLine($"Command: {context.CommandName}"); Console.WriteLine($"Result: {x + y}"); }); app.Run(args); internal class AuthFilter(ConsoleAppFilter next) : ConsoleAppFilter(next) { public override async Task InvokeAsync(ConsoleAppContext context, CancellationToken cancellationToken) { var state = new AppState(Guid.NewGuid(), "user-123"); var newContext = context with { State = state }; await Next.InvokeAsync(newContext, cancellationToken); } } record AppState(Guid RequestId, string UserId); var app2 = ConsoleApp.Create(); app2.Add("run", (string project, ConsoleAppContext context) => { Console.WriteLine($"Arguments: {string.Join(" ", context.Arguments)}"); Console.WriteLine($"Command Args: {string.Join(" ", context.CommandArguments.ToArray())}"); Console.WriteLine($"Escaped Args: {string.Join(" ", context.EscapedArguments.ToArray())}"); }); ``` -------------------------------- ### Generated Run Method Structure - C# Source: https://github.com/cysharp/consoleappframework/blob/master/ReadMe.md This snippet illustrates the internal structure of the `Run` method generated by ConsoleAppFramework. It shows how the framework creates the method signature based on the provided command's parameters and prepares for argument parsing. ```csharp internal static partial class ConsoleApp { // Generate the Run method itself with arguments and body to match the lambda expression public static void Run(string[] args, Action command) { // code body } } ``` -------------------------------- ### Implement Positional Arguments Source: https://context7.com/cysharp/consoleappframework/llms.txt Demonstrates the use of the Argument attribute to capture values based on their position in the command line, including support for params arrays. ```csharp using ConsoleAppFramework; ConsoleApp.Run(args, ([Argument] string input, [Argument] string output, bool dryRun) => { Console.WriteLine($"Input: {input}, Output: {output}, DryRun: {dryRun}"); }); ConsoleApp.Run(args, (string message, [Argument] params string[] files) => { Console.WriteLine(message); foreach (var file in files) Console.WriteLine($" - {file}"); }); ConsoleApp.Run(args, ([Argument] string title, [Argument] params int[] numbers) => { Console.WriteLine($"{title}: {string.Join(", ", numbers)}"); }); ```