mirror of
				https://github.com/spectreconsole/spectre.console.git
				synced 2025-10-25 15:19:23 +00:00 
			
		
		
		
	Compare commits
	
		
			10 Commits
		
	
	
		
			2d9e8069fd
			...
			renovate/d
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | 9f622f3123 | ||
|  | e51812237e | ||
|  | 749f0fded8 | ||
|  | f5f61ca610 | ||
|  | d90e94dbb3 | ||
|  | 169abca986 | ||
|  | 3c2156268c | ||
|  | 6fb81103f0 | ||
|  | 880e83b27c | ||
|  | 0b270e1ccd | 
							
								
								
									
										4
									
								
								.github/workflows/ci.yaml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								.github/workflows/ci.yaml
									
									
									
									
										vendored
									
									
								
							| @@ -18,12 +18,12 @@ jobs: | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - name: Checkout | ||||
|         uses: actions/checkout@v4 | ||||
|         uses: actions/checkout@v5 | ||||
|         with: | ||||
|           fetch-depth: 0 | ||||
|  | ||||
|       - name: Setup .NET SDK | ||||
|         uses: actions/setup-dotnet@v4 | ||||
|         uses: actions/setup-dotnet@v5 | ||||
|         with: | ||||
|           dotnet-version: | | ||||
|             8.0.x | ||||
|   | ||||
							
								
								
									
										12
									
								
								.github/workflows/publish.yaml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										12
									
								
								.github/workflows/publish.yaml
									
									
									
									
										vendored
									
									
								
							| @@ -24,12 +24,12 @@ jobs: | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - name: Checkout | ||||
|         uses: actions/checkout@v4 | ||||
|         uses: actions/checkout@v5 | ||||
|         with: | ||||
|           fetch-depth: 0 | ||||
|  | ||||
|       - name: Setup .NET SDK | ||||
|         uses: actions/setup-dotnet@v4 | ||||
|         uses: actions/setup-dotnet@v5 | ||||
|         with: | ||||
|           dotnet-version: | | ||||
|             8.0.x | ||||
| @@ -53,17 +53,17 @@ jobs: | ||||
|     runs-on: windows-latest | ||||
|     steps: | ||||
|     - name: Checkout | ||||
|       uses: actions/checkout@v4 | ||||
|       uses: actions/checkout@v5 | ||||
|       with: | ||||
|         fetch-depth: 0 | ||||
|  | ||||
|     - name: Setup .NET SDK | ||||
|       uses: actions/setup-dotnet@v4 | ||||
|       uses: actions/setup-dotnet@v5 | ||||
|  | ||||
|     - name: Setup Node.js | ||||
|       uses: actions/setup-node@v4 | ||||
|       uses: actions/setup-node@v5 | ||||
|       with: | ||||
|         node-version: '16' | ||||
|         node-version: '22' | ||||
|  | ||||
|     - name: Cache dependencies | ||||
|       uses: actions/cache@v4 | ||||
|   | ||||
| @@ -38,8 +38,8 @@ | ||||
|   </ItemGroup> | ||||
|  | ||||
|   <ItemGroup> | ||||
|     <PackageReference Include="Microsoft.Playwright" Version="1.52.0" /> | ||||
|     <PackageReference Include="Newtonsoft.Json" Version="13.0.3" /> | ||||
|     <PackageReference Include="Microsoft.Playwright" Version="1.55.0" /> | ||||
|     <PackageReference Include="Newtonsoft.Json" Version="13.0.4" /> | ||||
|     <PackageReference Include="Statiq.CodeAnalysis" Version="1.0.0-beta.72" /> | ||||
|     <PackageReference Include="Statiq.Common" Version="1.0.0-beta.72" /> | ||||
|     <PackageReference Include="Statiq.Web" Version="1.0.0-beta.60" /> | ||||
|   | ||||
| @@ -1,25 +0,0 @@ | ||||
|  | ||||
| Microsoft Visual Studio Solution File, Format Version 12.00 | ||||
| # Visual Studio Version 16 | ||||
| VisualStudioVersion = 16.0.30011.22 | ||||
| MinimumVisualStudioVersion = 10.0.40219.1 | ||||
| Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Docs", "Docs.csproj", "{C337F609-A890-4E52-BDA3-91658039B0E3}" | ||||
| EndProject | ||||
| Global | ||||
| 	GlobalSection(SolutionConfigurationPlatforms) = preSolution | ||||
| 		Debug|Any CPU = Debug|Any CPU | ||||
| 		Release|Any CPU = Release|Any CPU | ||||
| 	EndGlobalSection | ||||
| 	GlobalSection(ProjectConfigurationPlatforms) = postSolution | ||||
| 		{C337F609-A890-4E52-BDA3-91658039B0E3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||||
| 		{C337F609-A890-4E52-BDA3-91658039B0E3}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||||
| 		{C337F609-A890-4E52-BDA3-91658039B0E3}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||||
| 		{C337F609-A890-4E52-BDA3-91658039B0E3}.Release|Any CPU.Build.0 = Release|Any CPU | ||||
| 	EndGlobalSection | ||||
| 	GlobalSection(SolutionProperties) = preSolution | ||||
| 		HideSolutionNode = FALSE | ||||
| 	EndGlobalSection | ||||
| 	GlobalSection(ExtensibilityGlobals) = postSolution | ||||
| 		SolutionGuid = {2FB3922B-494A-45EB-A479-FC507B8E107C} | ||||
| 	EndGlobalSection | ||||
| EndGlobal | ||||
							
								
								
									
										3
									
								
								docs/Docs.slnx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								docs/Docs.slnx
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | ||||
| <Solution> | ||||
|   <Project Path="Docs.csproj" /> | ||||
| </Solution> | ||||
| @@ -1,6 +0,0 @@ | ||||
| { | ||||
|   "sdk": { | ||||
|     "version": "9.0.202", | ||||
|     "rollForward": "latestFeature" | ||||
|   } | ||||
| } | ||||
| @@ -0,0 +1,17 @@ | ||||
| Title: Spectre.Console 0.52.0 released! | ||||
| Description: Don't eat (too much) glue. | ||||
| Published: 2025-10-10 | ||||
| Category: Release Notes | ||||
| Excluded: false | ||||
| --- | ||||
|  | ||||
| Version `0.52.0` of Spectre.Console has been released! | ||||
|  | ||||
| Exciting things are happening. We’ve merged support for my love child, OpenCli, in this release. That means you can now pass the parameter `--help-dump-opencli` to your application to get an [OpenCli](https://opencli.org) description dumped to stdout. | ||||
|  | ||||
| ## What's Changed | ||||
|  | ||||
| * Add OpenCLI integration to Spectre.Console.Cli by [@patriksvensson](https://github.com/patriksvensson) in [#1909](https://github.com/spectreconsole/spectre.console/pull/1909) | ||||
| * Fix OPENCLI_VISIBILITY_INTERNAL to DefineConstants concat by [@devlead](https://github.com/devlead) in [#1912](https://github.com/spectreconsole/spectre.console/pull/1912) | ||||
|  | ||||
| **Full Changelog**: https://github.com/spectreconsole/spectre.console/compare/0.51.1...0.52.0 | ||||
| @@ -18,7 +18,7 @@ public class HelloCommand : Command<HelloCommand.Settings> | ||||
|     } | ||||
|  | ||||
|  | ||||
|     public override int Execute(CommandContext context, Settings settings) | ||||
|     public override int Execute(CommandContext context, Settings settings, CancellationToken cancellationToken) | ||||
|     { | ||||
|         AnsiConsole.MarkupLine($"Hello, [blue]{settings.Name}[/]"); | ||||
|         return 0; | ||||
|   | ||||
| @@ -55,7 +55,7 @@ in the previous step. | ||||
| ```csharp | ||||
| public class AddPackageCommand : Command<AddPackageSettings> | ||||
| { | ||||
|     public override int Execute(CommandContext context, AddPackageSettings settings) | ||||
|     public override int Execute(CommandContext context, AddPackageSettings settings, CancellationToken cancellationToken) | ||||
|     { | ||||
|         // Omitted | ||||
|         return 0; | ||||
| @@ -64,7 +64,7 @@ public class AddPackageCommand : Command<AddPackageSettings> | ||||
|  | ||||
| public class AddReferenceCommand : Command<AddReferenceSettings> | ||||
| { | ||||
|     public override int Execute(CommandContext context, AddReferenceSettings settings) | ||||
|     public override int Execute(CommandContext context, AddReferenceSettings settings, CancellationToken cancellationToken) | ||||
|     { | ||||
|         // Omitted | ||||
|         return 0; | ||||
|   | ||||
| @@ -33,7 +33,7 @@ internal sealed class FileSizeCommand : Command<FileSizeCommand.Settings> | ||||
|         public bool IncludeHidden { get; init; } | ||||
|     } | ||||
|  | ||||
|     public override int Execute([NotNull] CommandContext context, [NotNull] Settings settings) | ||||
|     public override int Execute(CommandContext context, Settings settings, CancellationToken cancellationToken) | ||||
|     { | ||||
|         var searchOptions = new EnumerationOptions | ||||
|         { | ||||
|   | ||||
| @@ -61,7 +61,7 @@ in the previous step. | ||||
| ```csharp | ||||
| public class AddPackageCommand : Command<AddPackageSettings> | ||||
| { | ||||
|     public override int Execute(CommandContext context, AddPackageSettings settings) | ||||
|     public override int Execute(CommandContext context, AddPackageSettings settings, CancellationToken cancellationToken) | ||||
|     { | ||||
|         // Omitted | ||||
|         return 0; | ||||
| @@ -70,7 +70,7 @@ public class AddPackageCommand : Command<AddPackageSettings> | ||||
|  | ||||
| public class AddReferenceCommand : Command<AddReferenceSettings> | ||||
| { | ||||
|     public override int Execute(CommandContext context, AddReferenceSettings settings) | ||||
|     public override int Execute(CommandContext context, AddReferenceSettings settings, CancellationToken cancellationToken) | ||||
|     { | ||||
|         // Omitted | ||||
|         return 0; | ||||
|   | ||||
| @@ -40,7 +40,7 @@ The following example validates the exit code and terminal output of a `Spectre. | ||||
|             _console = console; | ||||
|         } | ||||
|  | ||||
|         public override int Execute(CommandContext context) | ||||
|         public override int Execute(CommandContext context, CancellationToken cancellationToken) | ||||
|         { | ||||
|             _console.WriteLine("Hello world."); | ||||
|             return 0; | ||||
| @@ -78,7 +78,7 @@ public sealed class InteractiveCommandTests | ||||
|             _console = console; | ||||
|         } | ||||
|  | ||||
|         public override int Execute(CommandContext context) | ||||
|         public override int Execute(CommandContext context, CancellationToken cancellationToken) | ||||
|         { | ||||
|             var fruits = _console.Prompt( | ||||
|                 new MultiSelectionPrompt<string>() | ||||
|   | ||||
| @@ -3,7 +3,7 @@ | ||||
|   "isRoot": true, | ||||
|   "tools": { | ||||
|     "cake.tool": { | ||||
|       "version": "5.0.0", | ||||
|       "version": "5.1.0", | ||||
|       "commands": [ | ||||
|         "dotnet-cake" | ||||
|       ] | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| { | ||||
|   "$schema": "http://json.schemastore.org/global", | ||||
|   "sdk": { | ||||
|     "version": "9.0.202", | ||||
|     "version": "9.0.306", | ||||
|     "rollForward": "latestFeature" | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| using System.IO; | ||||
| using System.Threading; | ||||
| using Generator.Models; | ||||
| using Scriban; | ||||
| using Spectre.Console.Cli; | ||||
| @@ -21,7 +22,7 @@ namespace Generator.Commands | ||||
|             public string Input { get; set; } | ||||
|         } | ||||
|  | ||||
|         public override int Execute(CommandContext context, Settings settings) | ||||
|         public override int Execute(CommandContext context, Settings settings, CancellationToken cancellationToken) | ||||
|         { | ||||
|             var templates = new FilePath[] | ||||
|             { | ||||
|   | ||||
| @@ -2,6 +2,7 @@ using System.Collections.Generic; | ||||
| using System.IO; | ||||
| using System.Linq; | ||||
| using System.Net.Http; | ||||
| using System.Threading; | ||||
| using System.Threading.Tasks; | ||||
| using AngleSharp.Html.Parser; | ||||
| using Generator.Models; | ||||
| @@ -39,7 +40,7 @@ namespace Generator.Commands | ||||
|             _parser = new HtmlParser(); | ||||
|         } | ||||
|  | ||||
|         public override async Task<int> ExecuteAsync(CommandContext context, Settings settings) | ||||
|         public override async Task<int> ExecuteAsync(CommandContext context, Settings settings, CancellationToken cancellationToken) | ||||
|         { | ||||
|             var output = new DirectoryPath(settings.Output); | ||||
|             if (!_fileSystem.Directory.Exists(settings.Output)) | ||||
|   | ||||
| @@ -4,6 +4,7 @@ using System.Diagnostics.CodeAnalysis; | ||||
| using System.IO; | ||||
| using System.Linq; | ||||
| using System.Text; | ||||
| using System.Threading; | ||||
| using Generator.Commands.Samples; | ||||
| using Spectre.Console; | ||||
| using Spectre.Console.Cli; | ||||
| @@ -38,7 +39,7 @@ namespace Generator.Commands | ||||
|             _console = new AsciiCastConsole(console); | ||||
|         } | ||||
|  | ||||
|         public override int Execute([NotNull] CommandContext context, [NotNull] Settings settings) | ||||
|         public override int Execute([NotNull] CommandContext context, [NotNull] Settings settings, CancellationToken cancellationToken) | ||||
|         { | ||||
|             var samples = typeof(BaseSample).Assembly | ||||
|                 .GetTypes() | ||||
|   | ||||
| @@ -1,5 +1,6 @@ | ||||
| using System.Collections.Generic; | ||||
| using System.IO; | ||||
| using System.Threading; | ||||
| using Generator.Models; | ||||
| using Scriban; | ||||
| using Spectre.Console.Cli; | ||||
| @@ -16,7 +17,7 @@ namespace Generator.Commands | ||||
|             _fileSystem = new FileSystem(); | ||||
|         } | ||||
|  | ||||
|         public override int Execute(CommandContext context, GeneratorSettings settings) | ||||
|         public override int Execute(CommandContext context, GeneratorSettings settings, CancellationToken cancellationToken) | ||||
|         { | ||||
|             // Read the spinner model. | ||||
|             var spinners = new List<Spinner>(); | ||||
|   | ||||
| @@ -45,9 +45,9 @@ | ||||
|   <ItemGroup> | ||||
|     <PackageReference Include="AngleSharp" Version="1.3.0" /> | ||||
|     <PackageReference Include="Humanizer.Core" Version="2.14.1" /> | ||||
|     <PackageReference Include="Newtonsoft.Json" Version="13.0.3" /> | ||||
|     <PackageReference Include="Scriban" Version="6.2.1" /> | ||||
|     <PackageReference Include="Spectre.IO" Version="0.18.0" /> | ||||
|     <PackageReference Include="Newtonsoft.Json" Version="13.0.4" /> | ||||
|     <PackageReference Include="Scriban" Version="6.4.0" /> | ||||
|     <PackageReference Include="Spectre.IO" Version="0.20.0" /> | ||||
|   </ItemGroup> | ||||
|  | ||||
|   <ItemGroup> | ||||
|   | ||||
| @@ -100,5 +100,8 @@ dotnet_diagnostic.RCS1047.severity = none | ||||
| # RCS1090: Call 'ConfigureAwait(false)'. | ||||
| dotnet_diagnostic.RCS1090.severity = warning | ||||
|  | ||||
| # The file header is missing or not located at the top of the file | ||||
| dotnet_diagnostic.SA1633.severity = none | ||||
| # SA1633: The file header is missing or not located at the top of the file | ||||
| dotnet_diagnostic.SA1633.severity = none | ||||
|  | ||||
| # CA2016: Forward the CancellationToken parameter to methods that take one | ||||
| dotnet_diagnostic.CA2016.severity = warning | ||||
| @@ -4,23 +4,23 @@ | ||||
|   </PropertyGroup> | ||||
|   <ItemGroup> | ||||
|     <PackageVersion Include="IsExternalInit" Version="1.0.3" /> | ||||
|     <PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="9.0.3" /> | ||||
|     <PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.14.1" /> | ||||
|     <PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="9.0.10" /> | ||||
|     <PackageVersion Include="Microsoft.NET.Test.Sdk" Version="18.0.0" /> | ||||
|     <PackageVersion Include="Microsoft.SourceLink.GitHub" PrivateAssets="All" Version="8.0.0" /> | ||||
|     <PackageVersion Include="MinVer" PrivateAssets="All" Version="6.0.0" /> | ||||
|     <PackageVersion Include="OpenCli.Sources" Version="0.5.0" /> | ||||
|     <PackageVersion Include="PolySharp" Version="1.15.0" /> | ||||
|     <PackageVersion Include="Roslynator.Analyzers" PrivateAssets="All" Version="4.14.0" /> | ||||
|     <PackageVersion Include="Roslynator.Analyzers" PrivateAssets="All" Version="4.14.1" /> | ||||
|     <PackageVersion Include="Shouldly" Version="4.3.0" /> | ||||
|     <PackageVersion Include="SixLabors.ImageSharp" Version="3.1.11" /> | ||||
|     <PackageVersion Include="Spectre.Verify.Extensions" Version="28.16.0" /> | ||||
|     <PackageVersion Include="StyleCop.Analyzers" PrivateAssets="All" Version="1.2.0-beta.556" /> | ||||
|     <PackageVersion Include="System.Memory" Version="4.6.3" /> | ||||
|     <PackageVersion Include="TunnelVisionLabs.ReferenceAssemblyAnnotator" Version="1.0.0-alpha.160" /> | ||||
|     <PackageVersion Include="Verify.Xunit" Version="30.5.0" /> | ||||
|     <PackageVersion Include="Wcwidth.Sources" Version="2.0.0" /> | ||||
|     <PackageVersion Include="Verify.Xunit" Version="31.0.1" /> | ||||
|     <PackageVersion Include="Wcwidth.Sources" Version="3.0.0" /> | ||||
|     <PackageVersion Include="xunit" Version="2.9.3" /> | ||||
|     <PackageVersion Include="xunit.runner.visualstudio" Version="3.1.3"> | ||||
|     <PackageVersion Include="xunit.runner.visualstudio" Version="3.1.5"> | ||||
|       <PrivateAssets>all</PrivateAssets> | ||||
|       <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> | ||||
|     </PackageVersion> | ||||
|   | ||||
| @@ -9,19 +9,20 @@ public abstract class AsyncCommand : ICommand<EmptyCommandSettings> | ||||
|     /// Executes the command. | ||||
|     /// </summary> | ||||
|     /// <param name="context">The command context.</param> | ||||
|     /// <param name="cancellationToken">A <see cref="CancellationToken"/> that can be used to abort the command.</param> | ||||
|     /// <returns>An integer indicating whether or not the command executed successfully.</returns> | ||||
|     public abstract Task<int> ExecuteAsync(CommandContext context); | ||||
|     public abstract Task<int> ExecuteAsync(CommandContext context, CancellationToken cancellationToken); | ||||
|  | ||||
|     /// <inheritdoc/> | ||||
|     Task<int> ICommand<EmptyCommandSettings>.Execute(CommandContext context, EmptyCommandSettings settings) | ||||
|     Task<int> ICommand<EmptyCommandSettings>.ExecuteAsync(CommandContext context, EmptyCommandSettings settings, CancellationToken cancellationToken) | ||||
|     { | ||||
|         return ExecuteAsync(context); | ||||
|         return ExecuteAsync(context, cancellationToken); | ||||
|     } | ||||
|  | ||||
|     /// <inheritdoc/> | ||||
|     Task<int> ICommand.Execute(CommandContext context, CommandSettings settings) | ||||
|     Task<int> ICommand.ExecuteAsync(CommandContext context, CommandSettings settings, CancellationToken cancellationToken) | ||||
|     { | ||||
|         return ExecuteAsync(context); | ||||
|         return ExecuteAsync(context, cancellationToken); | ||||
|     } | ||||
|  | ||||
|     /// <inheritdoc/> | ||||
|   | ||||
| @@ -23,8 +23,9 @@ public abstract class AsyncCommand<TSettings> : ICommand<TSettings> | ||||
|     /// </summary> | ||||
|     /// <param name="context">The command context.</param> | ||||
|     /// <param name="settings">The settings.</param> | ||||
|     /// <param name="cancellationToken">A <see cref="CancellationToken"/> that can be used to abort the command.</param> | ||||
|     /// <returns>An integer indicating whether or not the command executed successfully.</returns> | ||||
|     public abstract Task<int> ExecuteAsync(CommandContext context, TSettings settings); | ||||
|     public abstract Task<int> ExecuteAsync(CommandContext context, TSettings settings, CancellationToken cancellationToken); | ||||
|  | ||||
|     /// <inheritdoc/> | ||||
|     ValidationResult ICommand.Validate(CommandContext context, CommandSettings settings) | ||||
| @@ -33,15 +34,15 @@ public abstract class AsyncCommand<TSettings> : ICommand<TSettings> | ||||
|     } | ||||
|  | ||||
|     /// <inheritdoc/> | ||||
|     Task<int> ICommand.Execute(CommandContext context, CommandSettings settings) | ||||
|     Task<int> ICommand.ExecuteAsync(CommandContext context, CommandSettings settings, CancellationToken cancellationToken) | ||||
|     { | ||||
|         Debug.Assert(settings is TSettings, "Command settings is of unexpected type."); | ||||
|         return ExecuteAsync(context, (TSettings)settings); | ||||
|         return ExecuteAsync(context, (TSettings)settings, cancellationToken); | ||||
|     } | ||||
|  | ||||
|     /// <inheritdoc/> | ||||
|     Task<int> ICommand<TSettings>.Execute(CommandContext context, TSettings settings) | ||||
|     Task<int> ICommand<TSettings>.ExecuteAsync(CommandContext context, TSettings settings, CancellationToken cancellationToken) | ||||
|     { | ||||
|         return ExecuteAsync(context, settings); | ||||
|         return ExecuteAsync(context, settings, cancellationToken); | ||||
|     } | ||||
| } | ||||
| @@ -10,19 +10,20 @@ public abstract class Command : ICommand<EmptyCommandSettings> | ||||
|     /// Executes the command. | ||||
|     /// </summary> | ||||
|     /// <param name="context">The command context.</param> | ||||
|     /// <param name="cancellationToken">A <see cref="CancellationToken"/> that can be used to abort the command.</param> | ||||
|     /// <returns>An integer indicating whether or not the command executed successfully.</returns> | ||||
|     public abstract int Execute(CommandContext context); | ||||
|     public abstract int Execute(CommandContext context, CancellationToken cancellationToken); | ||||
|  | ||||
|     /// <inheritdoc/> | ||||
|     Task<int> ICommand<EmptyCommandSettings>.Execute(CommandContext context, EmptyCommandSettings settings) | ||||
|     Task<int> ICommand<EmptyCommandSettings>.ExecuteAsync(CommandContext context, EmptyCommandSettings settings, CancellationToken cancellationToken) | ||||
|     { | ||||
|         return Task.FromResult(Execute(context)); | ||||
|         return Task.FromResult(Execute(context, cancellationToken)); | ||||
|     } | ||||
|  | ||||
|     /// <inheritdoc/> | ||||
|     Task<int> ICommand.Execute(CommandContext context, CommandSettings settings) | ||||
|     Task<int> ICommand.ExecuteAsync(CommandContext context, CommandSettings settings, CancellationToken cancellationToken) | ||||
|     { | ||||
|         return Task.FromResult(Execute(context)); | ||||
|         return Task.FromResult(Execute(context, cancellationToken)); | ||||
|     } | ||||
|  | ||||
|     /// <inheritdoc/> | ||||
|   | ||||
| @@ -26,10 +26,7 @@ public sealed class CommandApp : ICommandApp | ||||
|         _executor = new CommandExecutor(registrar); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Configures the command line application. | ||||
|     /// </summary> | ||||
|     /// <param name="configuration">The configuration.</param> | ||||
|     /// <inheritdoc/> | ||||
|     public void Configure(Action<IConfigurator> configuration) | ||||
|     { | ||||
|         if (configuration == null) | ||||
| @@ -51,22 +48,14 @@ public sealed class CommandApp : ICommandApp | ||||
|         return new DefaultCommandConfigurator(GetConfigurator().SetDefaultCommand<TCommand>()); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Runs the command line application with specified arguments. | ||||
|     /// </summary> | ||||
|     /// <param name="args">The arguments.</param> | ||||
|     /// <returns>The exit code from the executed command.</returns> | ||||
|     public int Run(IEnumerable<string> args) | ||||
|     /// <inheritdoc/> | ||||
|     public int Run(IEnumerable<string> args, CancellationToken cancellationToken = default) | ||||
|     { | ||||
|         return RunAsync(args).GetAwaiter().GetResult(); | ||||
|         return RunAsync(args, cancellationToken).GetAwaiter().GetResult(); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Runs the command line application with specified arguments. | ||||
|     /// </summary> | ||||
|     /// <param name="args">The arguments.</param> | ||||
|     /// <returns>The exit code from the executed command.</returns> | ||||
|     public async Task<int> RunAsync(IEnumerable<string> args) | ||||
|     /// <inheritdoc/> | ||||
|     public async Task<int> RunAsync(IEnumerable<string> args, CancellationToken cancellationToken = default) | ||||
|     { | ||||
|         try | ||||
|         { | ||||
| @@ -86,7 +75,7 @@ public sealed class CommandApp : ICommandApp | ||||
|             } | ||||
|  | ||||
|             return await _executor | ||||
|                 .Execute(_configurator, args) | ||||
|                 .ExecuteAsync(_configurator, args, cancellationToken) | ||||
|                 .ConfigureAwait(false); | ||||
|         } | ||||
|         catch (Exception ex) | ||||
| @@ -109,6 +98,11 @@ public sealed class CommandApp : ICommandApp | ||||
|                 return _configurator.Settings.ExceptionHandler(ex, null); | ||||
|             } | ||||
|  | ||||
|             if (ex is OperationCanceledException) | ||||
|             { | ||||
|                 return _configurator.Settings.CancellationExitCode; | ||||
|             } | ||||
|  | ||||
|             // Render the exception. | ||||
|             var pretty = GetRenderableErrorMessage(ex); | ||||
|             if (pretty != null) | ||||
|   | ||||
| @@ -25,33 +25,22 @@ public sealed class CommandApp<TDefaultCommand> : ICommandApp | ||||
|         _defaultCommandConfigurator = _app.SetDefaultCommand<TDefaultCommand>(); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Configures the command line application. | ||||
|     /// </summary> | ||||
|     /// <param name="configuration">The configuration.</param> | ||||
|     /// <inheritdoc/> | ||||
|     public void Configure(Action<IConfigurator> configuration) | ||||
|     { | ||||
|         _app.Configure(configuration); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Runs the command line application with specified arguments. | ||||
|     /// </summary> | ||||
|     /// <param name="args">The arguments.</param> | ||||
|     /// <returns>The exit code from the executed command.</returns> | ||||
|     public int Run(IEnumerable<string> args) | ||||
|     /// <inheritdoc/> | ||||
|     public int Run(IEnumerable<string> args, CancellationToken cancellationToken = default) | ||||
|     { | ||||
|         return _app.Run(args); | ||||
|         return _app.Run(args, cancellationToken); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Runs the command line application with specified arguments. | ||||
|     /// </summary> | ||||
|     /// <param name="args">The arguments.</param> | ||||
|     /// <returns>The exit code from the executed command.</returns> | ||||
|     public Task<int> RunAsync(IEnumerable<string> args) | ||||
|     /// <inheritdoc/> | ||||
|     public Task<int> RunAsync(IEnumerable<string> args, CancellationToken cancellationToken = default) | ||||
|     { | ||||
|         return _app.RunAsync(args); | ||||
|         return _app.RunAsync(args, cancellationToken); | ||||
|     } | ||||
|  | ||||
|     internal Configurator GetConfigurator() | ||||
|   | ||||
| @@ -24,8 +24,9 @@ public abstract class Command<TSettings> : ICommand<TSettings> | ||||
|     /// </summary> | ||||
|     /// <param name="context">The command context.</param> | ||||
|     /// <param name="settings">The settings.</param> | ||||
|     /// <param name="cancellationToken">A <see cref="CancellationToken"/> that can be used to abort the command.</param> | ||||
|     /// <returns>An integer indicating whether or not the command executed successfully.</returns> | ||||
|     public abstract int Execute(CommandContext context, TSettings settings); | ||||
|     public abstract int Execute(CommandContext context, TSettings settings, CancellationToken cancellationToken); | ||||
|  | ||||
|     /// <inheritdoc/> | ||||
|     ValidationResult ICommand.Validate(CommandContext context, CommandSettings settings) | ||||
| @@ -34,15 +35,15 @@ public abstract class Command<TSettings> : ICommand<TSettings> | ||||
|     } | ||||
|  | ||||
|     /// <inheritdoc/> | ||||
|     Task<int> ICommand.Execute(CommandContext context, CommandSettings settings) | ||||
|     Task<int> ICommand.ExecuteAsync(CommandContext context, CommandSettings settings, CancellationToken cancellationToken) | ||||
|     { | ||||
|         Debug.Assert(settings is TSettings, "Command settings is of unexpected type."); | ||||
|         return Task.FromResult(Execute(context, (TSettings)settings)); | ||||
|         return Task.FromResult(Execute(context, (TSettings)settings, cancellationToken)); | ||||
|     } | ||||
|  | ||||
|     /// <inheritdoc/> | ||||
|     Task<int> ICommand<TSettings>.Execute(CommandContext context, TSettings settings) | ||||
|     Task<int> ICommand<TSettings>.ExecuteAsync(CommandContext context, TSettings settings, CancellationToken cancellationToken) | ||||
|     { | ||||
|         return Task.FromResult(Execute(context, settings)); | ||||
|         return Task.FromResult(Execute(context, settings, cancellationToken)); | ||||
|     } | ||||
| } | ||||
| @@ -201,6 +201,24 @@ public static class ConfiguratorExtensions | ||||
|         return configurator; | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Tells the command line application to return the specified exit code when it's aborted through the <see cref="CancellationToken"/>. | ||||
|     /// The default cancellation exit code is 130. | ||||
|     /// </summary> | ||||
|     /// <param name="configurator">The configurator.</param> | ||||
|     /// <param name="exitCode">The exit code to return in case of cancellation.</param> | ||||
|     /// <returns>A configurator that can be used to configure the application further.</returns> | ||||
|     public static IConfigurator CancellationExitCode(this IConfigurator configurator, int exitCode) | ||||
|     { | ||||
|         if (configurator == null) | ||||
|         { | ||||
|             throw new ArgumentNullException(nameof(configurator)); | ||||
|         } | ||||
|  | ||||
|         configurator.Settings.CancellationExitCode = exitCode; | ||||
|         return configurator; | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Configures case sensitivity. | ||||
|     /// </summary> | ||||
| @@ -304,14 +322,14 @@ public static class ConfiguratorExtensions | ||||
|     public static ICommandConfigurator AddDelegate( | ||||
|         this IConfigurator configurator, | ||||
|         string name, | ||||
|         Func<CommandContext, int> func) | ||||
|         Func<CommandContext, CancellationToken, int> func) | ||||
|     { | ||||
|         if (configurator == null) | ||||
|         { | ||||
|             throw new ArgumentNullException(nameof(configurator)); | ||||
|         } | ||||
|  | ||||
|         return configurator.AddDelegate<EmptyCommandSettings>(name, (c, _) => func(c)); | ||||
|         return configurator.AddDelegate<EmptyCommandSettings>(name, (c, _, ct) => func(c, ct)); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
| @@ -324,14 +342,14 @@ public static class ConfiguratorExtensions | ||||
|     public static ICommandConfigurator AddAsyncDelegate( | ||||
|         this IConfigurator configurator, | ||||
|         string name, | ||||
|         Func<CommandContext, Task<int>> func) | ||||
|         Func<CommandContext, CancellationToken, Task<int>> func) | ||||
|     { | ||||
|         if (configurator == null) | ||||
|         { | ||||
|             throw new ArgumentNullException(nameof(configurator)); | ||||
|         } | ||||
|  | ||||
|         return configurator.AddAsyncDelegate<EmptyCommandSettings>(name, (c, _) => func(c)); | ||||
|         return configurator.AddAsyncDelegate<EmptyCommandSettings>(name, (c, _, ct) => func(c, ct)); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
| @@ -345,7 +363,7 @@ public static class ConfiguratorExtensions | ||||
|     public static ICommandConfigurator AddDelegate<TSettings>( | ||||
|         this IConfigurator<TSettings>? configurator, | ||||
|         string name, | ||||
|         Func<CommandContext, int> func) | ||||
|         Func<CommandContext, CancellationToken, int> func) | ||||
|         where TSettings : CommandSettings | ||||
|     { | ||||
|         if (typeof(TSettings).IsAbstract) | ||||
| @@ -358,7 +376,7 @@ public static class ConfiguratorExtensions | ||||
|             throw new ArgumentNullException(nameof(configurator)); | ||||
|         } | ||||
|  | ||||
|         return configurator.AddDelegate<TSettings>(name, (c, _) => func(c)); | ||||
|         return configurator.AddDelegate<TSettings>(name, (c, _, ct) => func(c, ct)); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
| @@ -372,7 +390,7 @@ public static class ConfiguratorExtensions | ||||
|     public static ICommandConfigurator AddAsyncDelegate<TSettings>( | ||||
|         this IConfigurator<TSettings> configurator, | ||||
|         string name, | ||||
|         Func<CommandContext, Task<int>> func) | ||||
|         Func<CommandContext, CancellationToken, Task<int>> func) | ||||
|         where TSettings : CommandSettings | ||||
|     { | ||||
|         if (configurator == null) | ||||
| @@ -380,7 +398,7 @@ public static class ConfiguratorExtensions | ||||
|             throw new ArgumentNullException(nameof(configurator)); | ||||
|         } | ||||
|  | ||||
|         return configurator.AddAsyncDelegate<TSettings>(name, (c, _) => func(c)); | ||||
|         return configurator.AddAsyncDelegate<TSettings>(name, (c, _, ct) => func(c, ct)); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|   | ||||
| @@ -18,6 +18,7 @@ public interface ICommand | ||||
|     /// </summary> | ||||
|     /// <param name="context">The command context.</param> | ||||
|     /// <param name="settings">The settings.</param> | ||||
|     /// <param name="cancellationToken">A <see cref="CancellationToken"/> that can be used to abort the command.</param> | ||||
|     /// <returns>The validation result.</returns> | ||||
|     Task<int> Execute(CommandContext context, CommandSettings settings); | ||||
|     Task<int> ExecuteAsync(CommandContext context, CommandSettings settings, CancellationToken cancellationToken); | ||||
| } | ||||
| @@ -15,13 +15,15 @@ public interface ICommandApp | ||||
|     /// Runs the command line application with specified arguments. | ||||
|     /// </summary> | ||||
|     /// <param name="args">The arguments.</param> | ||||
|     /// <param name="cancellationToken">A <see cref="CancellationToken"/> that can be used to abort the application.</param> | ||||
|     /// <returns>The exit code from the executed command.</returns> | ||||
|     int Run(IEnumerable<string> args); | ||||
|     int Run(IEnumerable<string> args, CancellationToken cancellationToken = default); | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Runs the command line application with specified arguments. | ||||
|     /// </summary> | ||||
|     /// <param name="args">The arguments.</param> | ||||
|     /// <param name="cancellationToken">A <see cref="CancellationToken"/> that can be used to abort the application.</param> | ||||
|     /// <returns>The exit code from the executed command.</returns> | ||||
|     Task<int> RunAsync(IEnumerable<string> args); | ||||
|     Task<int> RunAsync(IEnumerable<string> args, CancellationToken cancellationToken = default); | ||||
| } | ||||
| @@ -88,6 +88,12 @@ public interface ICommandAppSettings | ||||
|     /// </summary> | ||||
|     bool PropagateExceptions { get; set; } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Gets or sets the value used as the application exit code when it's aborted through the <see cref="CancellationToken"/>. | ||||
|     /// The default cancellation exit code is 130. | ||||
|     /// </summary> | ||||
|     int CancellationExitCode { get; set; } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Gets or sets a value indicating whether or not examples should be validated. | ||||
|     /// </summary> | ||||
|   | ||||
| @@ -12,6 +12,7 @@ public interface ICommand<TSettings> : ICommandLimiter<TSettings> | ||||
|     /// </summary> | ||||
|     /// <param name="context">The command context.</param> | ||||
|     /// <param name="settings">The settings.</param> | ||||
|     /// <param name="cancellationToken">A <see cref="CancellationToken"/> that can be used to abort the command.</param> | ||||
|     /// <returns>An integer indicating whether or not the command executed successfully.</returns> | ||||
|     Task<int> Execute(CommandContext context, TSettings settings); | ||||
|     Task<int> ExecuteAsync(CommandContext context, TSettings settings, CancellationToken cancellationToken); | ||||
| } | ||||
| @@ -48,7 +48,7 @@ public interface IConfigurator | ||||
|     /// <param name="name">The name of the command.</param> | ||||
|     /// <param name="func">The delegate to execute as part of command execution.</param> | ||||
|     /// <returns>A command configurator that can be used to configure the command further.</returns> | ||||
|     ICommandConfigurator AddDelegate<TSettings>(string name, Func<CommandContext, TSettings, int> func) | ||||
|     ICommandConfigurator AddDelegate<TSettings>(string name, Func<CommandContext, TSettings, CancellationToken, int> func) | ||||
|         where TSettings : CommandSettings; | ||||
|  | ||||
|     /// <summary> | ||||
| @@ -58,7 +58,7 @@ public interface IConfigurator | ||||
|     /// <param name="name">The name of the command.</param> | ||||
|     /// <param name="func">The delegate to execute as part of command execution.</param> | ||||
|     /// <returns>A command configurator that can be used to configure the command further.</returns> | ||||
|     ICommandConfigurator AddAsyncDelegate<TSettings>(string name, Func<CommandContext, TSettings, Task<int>> func) | ||||
|     ICommandConfigurator AddAsyncDelegate<TSettings>(string name, Func<CommandContext, TSettings, CancellationToken, Task<int>> func) | ||||
|         where TSettings : CommandSettings; | ||||
|  | ||||
|     /// <summary> | ||||
|   | ||||
| @@ -54,7 +54,7 @@ public interface IConfigurator<in TSettings> | ||||
|     /// <param name="name">The name of the command.</param> | ||||
|     /// <param name="func">The delegate to execute as part of command execution.</param> | ||||
|     /// <returns>A command configurator that can be used to configure the command further.</returns> | ||||
|     ICommandConfigurator AddDelegate<TDerivedSettings>(string name, Func<CommandContext, TDerivedSettings, int> func) | ||||
|     ICommandConfigurator AddDelegate<TDerivedSettings>(string name, Func<CommandContext, TDerivedSettings, CancellationToken, int> func) | ||||
|         where TDerivedSettings : TSettings; | ||||
|  | ||||
|     /// <summary> | ||||
| @@ -64,7 +64,7 @@ public interface IConfigurator<in TSettings> | ||||
|     /// <param name="name">The name of the command.</param> | ||||
|     /// <param name="func">The delegate to execute as part of command execution.</param> | ||||
|     /// <returns>A command configurator that can be used to configure the command further.</returns> | ||||
|     ICommandConfigurator AddAsyncDelegate<TDerivedSettings>(string name, Func<CommandContext, TDerivedSettings, Task<int>> func) | ||||
|     ICommandConfigurator AddAsyncDelegate<TDerivedSettings>(string name, Func<CommandContext, TDerivedSettings, CancellationToken, Task<int>> func) | ||||
|         where TDerivedSettings : TSettings; | ||||
|  | ||||
|     /// <summary> | ||||
|   | ||||
| @@ -12,7 +12,7 @@ internal sealed class CommandExecutor | ||||
|         _registrar.Register(typeof(DefaultPairDeconstructor), typeof(DefaultPairDeconstructor)); | ||||
|     } | ||||
|  | ||||
|     public async Task<int> Execute(IConfiguration configuration, IEnumerable<string> args) | ||||
|     public async Task<int> ExecuteAsync(IConfiguration configuration, IEnumerable<string> args, CancellationToken cancellationToken) | ||||
|     { | ||||
|         CommandTreeParserResult parsedResult; | ||||
|  | ||||
| @@ -125,7 +125,7 @@ internal sealed class CommandExecutor | ||||
|                 leaf.Command.Data); | ||||
|  | ||||
|             // Execute the command tree. | ||||
|             return await Execute(leaf, parsedResult.Tree, context, resolver, configuration).ConfigureAwait(false); | ||||
|             return await ExecuteAsync(leaf, parsedResult.Tree, context, resolver, configuration, cancellationToken).ConfigureAwait(false); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @@ -222,12 +222,13 @@ internal sealed class CommandExecutor | ||||
|         return (parsedResult, tokenizerResult); | ||||
|     } | ||||
|  | ||||
|     private static async Task<int> Execute( | ||||
|     private static async Task<int> ExecuteAsync( | ||||
|         CommandTree leaf, | ||||
|         CommandTree tree, | ||||
|         CommandContext context, | ||||
|         ITypeResolver resolver, | ||||
|         IConfiguration configuration) | ||||
|         IConfiguration configuration, | ||||
|         CancellationToken cancellationToken) | ||||
|     { | ||||
|         try | ||||
|         { | ||||
| @@ -256,7 +257,7 @@ internal sealed class CommandExecutor | ||||
|             } | ||||
|  | ||||
|             // Execute the command. | ||||
|             var result = await command.Execute(context, settings); | ||||
|             var result = await command.ExecuteAsync(context, settings, cancellationToken); | ||||
|             foreach (var interceptor in interceptors) | ||||
|             { | ||||
|                 interceptor.InterceptResult(context, settings, ref result); | ||||
|   | ||||
| @@ -27,7 +27,7 @@ internal sealed class ExplainCommand : Command<ExplainCommand.Settings>, IBuiltI | ||||
|         public bool IncludeHidden { get; set; } | ||||
|     } | ||||
|  | ||||
|     public override int Execute(CommandContext context, Settings settings) | ||||
|     public override int Execute(CommandContext context, Settings settings, CancellationToken cancellationToken) | ||||
|     { | ||||
|         var tree = new Tree("CLI Configuration"); | ||||
|         tree.AddNode(ValueMarkup("Application Name", _commandModel.ApplicationName, "no application name")); | ||||
|   | ||||
| @@ -13,7 +13,7 @@ internal sealed class OpenCliGeneratorCommand : Command, IBuiltInCommand | ||||
|         _model = model ?? throw new ArgumentNullException(nameof(model)); | ||||
|     } | ||||
|  | ||||
|     public override int Execute(CommandContext context) | ||||
|     public override int Execute(CommandContext context, CancellationToken cancellationToken) | ||||
|     { | ||||
|         var document = new OpenCliDocument | ||||
|         { | ||||
|   | ||||
| @@ -11,7 +11,7 @@ internal sealed class VersionCommand : Command, IBuiltInCommand | ||||
|         _writer = configuration.Settings.Console.GetConsole(); | ||||
|     } | ||||
|  | ||||
|     public override int Execute(CommandContext context) | ||||
|     public override int Execute(CommandContext context, CancellationToken cancellationToken) | ||||
|     { | ||||
|         _writer.MarkupLine( | ||||
|             "[yellow]Spectre.Cli[/] version [aqua]{0}[/]", | ||||
|   | ||||
| @@ -13,7 +13,7 @@ internal sealed class XmlDocCommand : Command, IBuiltInCommand | ||||
|         _writer = configuration.Settings.Console.GetConsole(); | ||||
|     } | ||||
|  | ||||
|     public override int Execute(CommandContext context) | ||||
|     public override int Execute(CommandContext context, CancellationToken cancellationToken) | ||||
|     { | ||||
|         _writer.Write(Serialize(_model), Style.Plain); | ||||
|         return 0; | ||||
|   | ||||
| @@ -18,6 +18,7 @@ internal sealed class CommandAppSettings : ICommandAppSettings | ||||
|     public HelpProviderStyle? HelpProviderStyles { get; set; } | ||||
|     public bool StrictParsing { get; set; } | ||||
|     public bool ConvertFlagsToRemainingArguments { get; set; } | ||||
|     public int CancellationExitCode { get; set; } | ||||
|  | ||||
|     public ParsingMode ParsingMode => | ||||
|         StrictParsing ? ParsingMode.Strict : ParsingMode.Relaxed; | ||||
| @@ -33,6 +34,7 @@ internal sealed class CommandAppSettings : ICommandAppSettings | ||||
|         TrimTrailingPeriod = true; | ||||
|         HelpProviderStyles = HelpProviderStyle.Default; | ||||
|         ConvertFlagsToRemainingArguments = false; | ||||
|         CancellationExitCode = 130; | ||||
|     } | ||||
|  | ||||
|     public bool IsTrue(Func<CommandAppSettings, bool> func, string environmentVariableName) | ||||
|   | ||||
| @@ -56,19 +56,19 @@ internal sealed class Configurator : IUnsafeConfigurator, IConfigurator, IConfig | ||||
|         return new CommandConfigurator(command); | ||||
|     } | ||||
|  | ||||
|     public ICommandConfigurator AddDelegate<TSettings>(string name, Func<CommandContext, TSettings, int> func) | ||||
|     public ICommandConfigurator AddDelegate<TSettings>(string name, Func<CommandContext, TSettings, CancellationToken, int> func) | ||||
|         where TSettings : CommandSettings | ||||
|     { | ||||
|         var command = Commands.AddAndReturn(ConfiguredCommand.FromDelegate<TSettings>( | ||||
|             name, (context, settings) => Task.FromResult(func(context, (TSettings)settings)))); | ||||
|             name, (context, settings, cancellationToken) => Task.FromResult(func(context, (TSettings)settings, cancellationToken)))); | ||||
|         return new CommandConfigurator(command); | ||||
|     } | ||||
|  | ||||
|     public ICommandConfigurator AddAsyncDelegate<TSettings>(string name, Func<CommandContext, TSettings, Task<int>> func) | ||||
|     public ICommandConfigurator AddAsyncDelegate<TSettings>(string name, Func<CommandContext, TSettings, CancellationToken, Task<int>> func) | ||||
|         where TSettings : CommandSettings | ||||
|     { | ||||
|         var command = Commands.AddAndReturn(ConfiguredCommand.FromDelegate<TSettings>( | ||||
|             name, (context, settings) => func(context, (TSettings)settings))); | ||||
|             name, (context, settings, cancellationToken) => func(context, (TSettings)settings, cancellationToken))); | ||||
|         return new CommandConfigurator(command); | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -46,21 +46,21 @@ internal sealed class Configurator<TSettings> : IUnsafeBranchConfigurator, IConf | ||||
|         return configurator; | ||||
|     } | ||||
|  | ||||
|     public ICommandConfigurator AddDelegate<TDerivedSettings>(string name, Func<CommandContext, TDerivedSettings, int> func) | ||||
|     public ICommandConfigurator AddDelegate<TDerivedSettings>(string name, Func<CommandContext, TDerivedSettings, CancellationToken, int> func) | ||||
|         where TDerivedSettings : TSettings | ||||
|     { | ||||
|         var command = ConfiguredCommand.FromDelegate<TDerivedSettings>( | ||||
|             name, (context, settings) => Task.FromResult(func(context, (TDerivedSettings)settings))); | ||||
|             name, (context, settings, cancellationToken) => Task.FromResult(func(context, (TDerivedSettings)settings, cancellationToken))); | ||||
|  | ||||
|         _command.Children.Add(command); | ||||
|         return new CommandConfigurator(command); | ||||
|     } | ||||
|  | ||||
|     public ICommandConfigurator AddAsyncDelegate<TDerivedSettings>(string name, Func<CommandContext, TDerivedSettings, Task<int>> func) | ||||
|     public ICommandConfigurator AddAsyncDelegate<TDerivedSettings>(string name, Func<CommandContext, TDerivedSettings, CancellationToken, Task<int>> func) | ||||
|         where TDerivedSettings : TSettings | ||||
|     { | ||||
|         var command = ConfiguredCommand.FromDelegate<TDerivedSettings>( | ||||
|             name, (context, settings) => func(context, (TDerivedSettings)settings)); | ||||
|             name, (context, settings, cancellationToken) => func(context, (TDerivedSettings)settings, cancellationToken)); | ||||
|  | ||||
|         _command.Children.Add(command); | ||||
|         return new CommandConfigurator(command); | ||||
|   | ||||
| @@ -8,7 +8,7 @@ internal sealed class ConfiguredCommand | ||||
|     public object? Data { get; set; } | ||||
|     public Type? CommandType { get; } | ||||
|     public Type SettingsType { get; } | ||||
|     public Func<CommandContext, CommandSettings, Task<int>>? Delegate { get; } | ||||
|     public Func<CommandContext, CommandSettings, CancellationToken, Task<int>>? Delegate { get; } | ||||
|     public bool IsDefaultCommand { get; } | ||||
|     public bool IsHidden { get; set; } | ||||
|  | ||||
| @@ -19,7 +19,7 @@ internal sealed class ConfiguredCommand | ||||
|         string name, | ||||
|         Type? commandType, | ||||
|         Type settingsType, | ||||
|         Func<CommandContext, CommandSettings, Task<int>>? @delegate, | ||||
|         Func<CommandContext, CommandSettings, CancellationToken, Task<int>>? @delegate, | ||||
|         bool isDefaultCommand) | ||||
|     { | ||||
|         Name = name; | ||||
| @@ -60,7 +60,7 @@ internal sealed class ConfiguredCommand | ||||
|     } | ||||
|  | ||||
|     public static ConfiguredCommand FromDelegate<TSettings>( | ||||
|         string name, Func<CommandContext, CommandSettings, Task<int>>? @delegate = null) | ||||
|         string name, Func<CommandContext, CommandSettings, CancellationToken, Task<int>>? @delegate = null) | ||||
|         where TSettings : CommandSettings | ||||
|     { | ||||
|         return new ConfiguredCommand(name, null, typeof(TSettings), @delegate, false); | ||||
|   | ||||
| @@ -2,16 +2,16 @@ namespace Spectre.Console.Cli; | ||||
|  | ||||
| internal sealed class DelegateCommand : ICommand | ||||
| { | ||||
|     private readonly Func<CommandContext, CommandSettings, Task<int>> _func; | ||||
|     private readonly Func<CommandContext, CommandSettings, CancellationToken, Task<int>> _func; | ||||
|  | ||||
|     public DelegateCommand(Func<CommandContext, CommandSettings, Task<int>> func) | ||||
|     public DelegateCommand(Func<CommandContext, CommandSettings, CancellationToken, Task<int>> func) | ||||
|     { | ||||
|         _func = func; | ||||
|     } | ||||
|  | ||||
|     public Task<int> Execute(CommandContext context, CommandSettings settings) | ||||
|     public Task<int> ExecuteAsync(CommandContext context, CommandSettings settings, CancellationToken cancellationToken) | ||||
|     { | ||||
|         return _func(context, settings); | ||||
|         return _func(context, settings, cancellationToken); | ||||
|     } | ||||
|  | ||||
|     public ValidationResult Validate(CommandContext context, CommandSettings settings) | ||||
|   | ||||
| @@ -8,7 +8,7 @@ internal sealed class CommandInfo : ICommandContainer, ICommandInfo | ||||
|     public object? Data { get; } | ||||
|     public Type? CommandType { get; } | ||||
|     public Type SettingsType { get; } | ||||
|     public Func<CommandContext, CommandSettings, Task<int>>? Delegate { get; } | ||||
|     public Func<CommandContext, CommandSettings, CancellationToken, Task<int>>? Delegate { get; } | ||||
|     public bool IsDefaultCommand { get; } | ||||
|     public CommandInfo? Parent { get; } | ||||
|     public IList<CommandInfo> Children { get; } | ||||
|   | ||||
| @@ -98,7 +98,7 @@ public sealed class CommandAppTester | ||||
|     { | ||||
|         try | ||||
|         { | ||||
|             Run(args, Console, c => c.PropagateExceptions()); | ||||
|             RunAsync(args, Console, c => c.PropagateExceptions()).GetAwaiter().GetResult(); | ||||
|             throw new InvalidOperationException("Expected an exception to be thrown, but there was none."); | ||||
|         } | ||||
|         catch (T ex) | ||||
| @@ -129,53 +129,21 @@ public sealed class CommandAppTester | ||||
|     /// <returns>The result.</returns> | ||||
|     public CommandAppResult Run(params string[] args) | ||||
|     { | ||||
|         return Run(args, Console); | ||||
|     } | ||||
|  | ||||
|     private CommandAppResult Run(string[] args, TestConsole console, Action<IConfigurator>? config = null) | ||||
|     { | ||||
|         CommandContext? context = null; | ||||
|         CommandSettings? settings = null; | ||||
|  | ||||
|         var app = new CommandApp(Registrar); | ||||
|         _appConfiguration?.Invoke(app); | ||||
|  | ||||
|         if (_configuration != null) | ||||
|         { | ||||
|             app.Configure(_configuration); | ||||
|         } | ||||
|  | ||||
|         if (config != null) | ||||
|         { | ||||
|             app.Configure(config); | ||||
|         } | ||||
|  | ||||
|         app.Configure(c => c.ConfigureConsole(console)); | ||||
|         app.Configure(c => c.SetInterceptor(new CallbackCommandInterceptor((ctx, s) => | ||||
|         { | ||||
|             context = ctx; | ||||
|             settings = s; | ||||
|         }))); | ||||
|  | ||||
|         var result = app.Run(args); | ||||
|  | ||||
|         var output = console.Output.NormalizeLineEndings(); | ||||
|         output = TestSettings.TrimConsoleOutput ? output.TrimLines().Trim() : output; | ||||
|  | ||||
|         return new CommandAppResult(result, output, context, settings); | ||||
|         return RunAsync(args, Console).GetAwaiter().GetResult(); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Runs the command application asynchronously. | ||||
|     /// </summary> | ||||
|     /// <param name="args">The arguments.</param> | ||||
|     /// <param name="cancellationToken">The token to monitor for cancellation requests.</param> | ||||
|     /// <returns>The result.</returns> | ||||
|     public async Task<CommandAppResult> RunAsync(params string[] args) | ||||
|     public async Task<CommandAppResult> RunAsync(string[]? args = null, CancellationToken cancellationToken = default) | ||||
|     { | ||||
|         return await RunAsync(args, Console); | ||||
|         return await RunAsync(args ?? [], Console, cancellationToken: cancellationToken); | ||||
|     } | ||||
|  | ||||
|     private async Task<CommandAppResult> RunAsync(string[] args, TestConsole console, Action<IConfigurator>? config = null) | ||||
|     private async Task<CommandAppResult> RunAsync(string[] args, TestConsole console, Action<IConfigurator>? config = null, CancellationToken cancellationToken = default) | ||||
|     { | ||||
|         CommandContext? context = null; | ||||
|         CommandSettings? settings = null; | ||||
| @@ -200,7 +168,7 @@ public sealed class CommandAppTester | ||||
|             settings = s; | ||||
|         }))); | ||||
|  | ||||
|         var result = await app.RunAsync(args); | ||||
|         var result = await app.RunAsync(args, cancellationToken); | ||||
|  | ||||
|         var output = console.Output.NormalizeLineEndings(); | ||||
|         output = TestSettings.TrimConsoleOutput ? output.TrimLines().Trim() : output; | ||||
|   | ||||
| @@ -9,10 +9,10 @@ public sealed class AsynchronousCommand : AsyncCommand<AsynchronousCommandSettin | ||||
|         _console = console; | ||||
|     } | ||||
|  | ||||
|     public async override Task<int> ExecuteAsync(CommandContext context, AsynchronousCommandSettings settings) | ||||
|     public async override Task<int> ExecuteAsync(CommandContext context, AsynchronousCommandSettings settings, CancellationToken cancellationToken) | ||||
|     { | ||||
|         // Simulate a long running asynchronous task | ||||
|         await Task.Delay(200); | ||||
|         await Task.Delay(200, cancellationToken); | ||||
|  | ||||
|         if (settings.ThrowException) | ||||
|         { | ||||
|   | ||||
| @@ -2,7 +2,7 @@ namespace Spectre.Console.Tests.Data; | ||||
|  | ||||
| public class CatCommand : AnimalCommand<CatSettings> | ||||
| { | ||||
|     public override int Execute(CommandContext context, CatSettings settings) | ||||
|     public override int Execute(CommandContext context, CatSettings settings, CancellationToken cancellationToken) | ||||
|     { | ||||
|         return 0; | ||||
|     } | ||||
|   | ||||
| @@ -23,7 +23,7 @@ public class DogCommand : AnimalCommand<DogSettings> | ||||
|         return base.Validate(context, settings); | ||||
|     } | ||||
|  | ||||
|     public override int Execute(CommandContext context, DogSettings settings) | ||||
|     public override int Execute(CommandContext context, DogSettings settings, CancellationToken cancellationToken) | ||||
|     { | ||||
|         return 0; | ||||
|     } | ||||
|   | ||||
| @@ -9,7 +9,7 @@ public sealed class DumpRemainingCommand : Command<EmptyCommandSettings> | ||||
|         _console = console; | ||||
|     } | ||||
|  | ||||
|     public override int Execute(CommandContext context, EmptyCommandSettings settings) | ||||
|     public override int Execute(CommandContext context, EmptyCommandSettings settings, CancellationToken cancellationToken) | ||||
|     { | ||||
|         if (context.Remaining.Raw.Count > 0) | ||||
|         { | ||||
|   | ||||
| @@ -2,7 +2,7 @@ namespace Spectre.Console.Tests.Data; | ||||
|  | ||||
| public sealed class EmptyCommand : Command<EmptyCommandSettings> | ||||
| { | ||||
|     public override int Execute(CommandContext context, EmptyCommandSettings settings) | ||||
|     public override int Execute(CommandContext context, EmptyCommandSettings settings, CancellationToken cancellationToken) | ||||
|     { | ||||
|         return 0; | ||||
|     } | ||||
|   | ||||
| @@ -3,7 +3,7 @@ namespace Spectre.Console.Tests.Data; | ||||
| public sealed class GenericCommand<TSettings> : Command<TSettings> | ||||
|     where TSettings : CommandSettings | ||||
| { | ||||
|     public override int Execute(CommandContext context, TSettings settings) | ||||
|     public override int Execute(CommandContext context, TSettings settings, CancellationToken cancellationToken) | ||||
|     { | ||||
|         return 0; | ||||
|     } | ||||
|   | ||||
| @@ -3,7 +3,7 @@ namespace Spectre.Console.Tests.Data; | ||||
| [Description("The giraffe command.")] | ||||
| public sealed class GiraffeCommand : Command<GiraffeSettings> | ||||
| { | ||||
|     public override int Execute(CommandContext context, GiraffeSettings settings) | ||||
|     public override int Execute(CommandContext context, GiraffeSettings settings, CancellationToken cancellationToken) | ||||
|     { | ||||
|         return 0; | ||||
|     } | ||||
|   | ||||
| @@ -9,7 +9,7 @@ public class GreeterCommand : Command<OptionalArgumentWithDefaultValueSettings> | ||||
|         _console = console; | ||||
|     } | ||||
|  | ||||
|     public override int Execute(CommandContext context, OptionalArgumentWithDefaultValueSettings settings) | ||||
|     public override int Execute(CommandContext context, OptionalArgumentWithDefaultValueSettings settings, CancellationToken cancellationToken) | ||||
|     { | ||||
|         _console.WriteLine(settings.Greeting); | ||||
|         return 0; | ||||
|   | ||||
| @@ -2,7 +2,7 @@ namespace Spectre.Console.Tests.Data; | ||||
|  | ||||
| public sealed class HiddenOptionsCommand : Command<HiddenOptionSettings> | ||||
| { | ||||
|     public override int Execute(CommandContext context, HiddenOptionSettings settings) | ||||
|     public override int Execute(CommandContext context, HiddenOptionSettings settings, CancellationToken cancellationToken) | ||||
|     { | ||||
|         return 0; | ||||
|     } | ||||
|   | ||||
| @@ -3,7 +3,7 @@ namespace Spectre.Console.Tests.Data; | ||||
| [Description("The horse command.")] | ||||
| public class HorseCommand : AnimalCommand<HorseSettings> | ||||
| { | ||||
|     public override int Execute(CommandContext context, HorseSettings settings) | ||||
|     public override int Execute(CommandContext context, HorseSettings settings, CancellationToken cancellationToken) | ||||
|     { | ||||
|         return 0; | ||||
|     } | ||||
|   | ||||
| @@ -2,7 +2,7 @@ namespace Spectre.Console.Tests.Data; | ||||
|  | ||||
| public sealed class InvalidCommand : Command<InvalidSettings> | ||||
| { | ||||
|     public override int Execute(CommandContext context, InvalidSettings settings) | ||||
|     public override int Execute(CommandContext context, InvalidSettings settings, CancellationToken cancellationToken) | ||||
|     { | ||||
|         return 0; | ||||
|     } | ||||
|   | ||||
| @@ -3,7 +3,7 @@ namespace Spectre.Console.Tests.Data; | ||||
| [Description("The lion command.")] | ||||
| public class LionCommand : AnimalCommand<LionSettings> | ||||
| { | ||||
|     public override int Execute(CommandContext context, LionSettings settings) | ||||
|     public override int Execute(CommandContext context, LionSettings settings, CancellationToken cancellationToken) | ||||
|     { | ||||
|         return 0; | ||||
|     } | ||||
|   | ||||
| @@ -5,7 +5,7 @@ public sealed class NoDescriptionCommand : Command<EmptyCommandSettings> | ||||
|     [CommandOption("-f|--foo <VALUE>")] | ||||
|     public int Foo { get; set; } | ||||
|  | ||||
|     public override int Execute(CommandContext context, EmptyCommandSettings settings) | ||||
|     public override int Execute(CommandContext context, EmptyCommandSettings settings, CancellationToken cancellationToken) | ||||
|     { | ||||
|         return 0; | ||||
|     } | ||||
|   | ||||
| @@ -2,7 +2,7 @@ namespace Spectre.Console.Tests.Data; | ||||
|  | ||||
| public class OptionVectorCommand : Command<OptionVectorSettings> | ||||
| { | ||||
|     public override int Execute(CommandContext context, OptionVectorSettings settings) | ||||
|     public override int Execute(CommandContext context, OptionVectorSettings settings, CancellationToken cancellationToken) | ||||
|     { | ||||
|         return 0; | ||||
|     } | ||||
|   | ||||
| @@ -2,7 +2,7 @@ namespace Spectre.Console.Tests.Data; | ||||
|  | ||||
| public sealed class ThrowingCommand : Command<ThrowingCommandSettings> | ||||
| { | ||||
|     public override int Execute(CommandContext context, ThrowingCommandSettings settings) | ||||
|     public override int Execute(CommandContext context, ThrowingCommandSettings settings, CancellationToken cancellationToken) | ||||
|     { | ||||
|         throw new InvalidOperationException("W00t?"); | ||||
|     } | ||||
|   | ||||
| @@ -3,7 +3,7 @@ namespace Spectre.Console.Tests.Data; | ||||
| [Description("The turtle command.")] | ||||
| public class TurtleCommand : AnimalCommand<TurtleSettings> | ||||
| { | ||||
|     public override int Execute(CommandContext context, TurtleSettings settings) | ||||
|     public override int Execute(CommandContext context, TurtleSettings settings, CancellationToken cancellationToken) | ||||
|     { | ||||
|         return 0; | ||||
|     } | ||||
|   | ||||
| @@ -9,7 +9,7 @@ public sealed class VersionCommand : Command<VersionSettings> | ||||
|         _console = console; | ||||
|     } | ||||
|  | ||||
|     public override int Execute(CommandContext context, VersionSettings settings) | ||||
|     public override int Execute(CommandContext context, VersionSettings settings, CancellationToken cancellationToken) | ||||
|     { | ||||
|         _console.WriteLine($"VersionCommand ran, Version: {settings.Version ?? string.Empty}"); | ||||
|  | ||||
|   | ||||
| @@ -5,6 +5,7 @@ global using System.Diagnostics.CodeAnalysis; | ||||
| global using System.Globalization; | ||||
| global using System.Linq; | ||||
| global using System.Runtime.CompilerServices; | ||||
| global using System.Threading; | ||||
| global using System.Threading.Tasks; | ||||
| global using Shouldly; | ||||
| global using Spectre.Console.Cli; | ||||
|   | ||||
| @@ -53,7 +53,7 @@ public sealed partial class CommandAppTests | ||||
|             }); | ||||
|  | ||||
|             // When | ||||
|             var result = await Record.ExceptionAsync(async () => | ||||
|             var exception = await Record.ExceptionAsync(async () => | ||||
|                     await app.RunAsync(new[] | ||||
|                         { | ||||
|                         "--ThrowException", | ||||
| @@ -61,10 +61,64 @@ public sealed partial class CommandAppTests | ||||
|                         })); | ||||
|  | ||||
|             // Then | ||||
|             result.ShouldBeOfType<Exception>().And(ex => | ||||
|             exception.ShouldBeOfType<Exception>().And(ex => | ||||
|             { | ||||
|                 ex.Message.ShouldBe("Throwing exception asynchronously"); | ||||
|             }); | ||||
|         } | ||||
|  | ||||
|         [Fact] | ||||
|         public async Task Should_Throw_OperationCanceledException_When_Propagated_And_Cancelled() | ||||
|         { | ||||
|             // Given | ||||
|             var app = new CommandAppTester(); | ||||
|             app.SetDefaultCommand<AsynchronousCommand>(); | ||||
|             app.Configure(config => | ||||
|             { | ||||
|                 config.PropagateExceptions(); | ||||
|             }); | ||||
|  | ||||
|             // When | ||||
|             var exception = await Record.ExceptionAsync(async () => | ||||
|                 await app.RunAsync(cancellationToken: new CancellationToken(canceled: true))); | ||||
|  | ||||
|             // Then | ||||
|             exception.ShouldNotBeNull(); | ||||
|             exception.ShouldBeAssignableTo<OperationCanceledException>(); | ||||
|         } | ||||
|  | ||||
|         [Fact] | ||||
|         public async Task Should_Return_Default_Exit_Code_When_Cancelled() | ||||
|         { | ||||
|             // Given | ||||
|             var app = new CommandAppTester(); | ||||
|             app.SetDefaultCommand<AsynchronousCommand>(); | ||||
|  | ||||
|             // When | ||||
|             var result = await app.RunAsync(cancellationToken: new CancellationToken(canceled: true)); | ||||
|  | ||||
|             // Then | ||||
|             result.ExitCode.ShouldBe(130); | ||||
|             result.Output.ShouldBeEmpty(); | ||||
|         } | ||||
|  | ||||
|         [Fact] | ||||
|         public async Task Should_Return_Custom_Exit_Code_When_Cancelled() | ||||
|         { | ||||
|             // Given | ||||
|             var app = new CommandAppTester(); | ||||
|             app.SetDefaultCommand<AsynchronousCommand>(); | ||||
|             app.Configure(config => | ||||
|             { | ||||
|                 config.CancellationExitCode(123); | ||||
|             }); | ||||
|  | ||||
|             // When | ||||
|             var result = await app.RunAsync(cancellationToken: new CancellationToken(canceled: true)); | ||||
|  | ||||
|             // Then | ||||
|             result.ExitCode.ShouldBe(123); | ||||
|             result.Output.ShouldBeEmpty(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -28,12 +28,12 @@ public sealed partial class CommandAppTests | ||||
|  | ||||
|     public class NullableCommand : Command<NullableSettings> | ||||
|     { | ||||
|         public override int Execute(CommandContext context, NullableSettings settings) => 0; | ||||
|         public override int Execute(CommandContext context, NullableSettings settings, CancellationToken cancellationToken) => 0; | ||||
|     } | ||||
|  | ||||
|     public class NullableWithInitCommand : Command<NullableWithInitSettings> | ||||
|     { | ||||
|         public override int Execute(CommandContext context, NullableWithInitSettings settings) => 0; | ||||
|         public override int Execute(CommandContext context, NullableWithInitSettings settings, CancellationToken cancellationToken) => 0; | ||||
|     } | ||||
|  | ||||
|     [Fact] | ||||
|   | ||||
| @@ -19,7 +19,7 @@ public sealed partial class CommandAppTests | ||||
|                     _dep = dep; | ||||
|                 } | ||||
|  | ||||
|                 public override int Execute(CommandContext context, CustomInheritedCommandSettings settings) | ||||
|                 public override int Execute(CommandContext context, CustomInheritedCommandSettings settings, CancellationToken cancellationToken) | ||||
|                 { | ||||
|                     return 0; | ||||
|                 } | ||||
|   | ||||
| @@ -10,7 +10,7 @@ public sealed partial class CommandAppTests | ||||
|             { | ||||
|             } | ||||
|  | ||||
|             public override int Execute(CommandContext context, Settings settings) | ||||
|             public override int Execute(CommandContext context, Settings settings, CancellationToken cancellationToken) | ||||
|             { | ||||
|                 return 0; | ||||
|             } | ||||
|   | ||||
| @@ -1117,7 +1117,7 @@ public sealed partial class CommandAppTests | ||||
|             { | ||||
|                 config.PropagateExceptions(); | ||||
|                 config.AddDelegate<DogSettings>( | ||||
|                     "foo", (context, settings) => | ||||
|                     "foo", (context, settings, _) => | ||||
|                     { | ||||
|                         dog = settings; | ||||
|                         data = (int)context.Data; | ||||
| @@ -1145,7 +1145,7 @@ public sealed partial class CommandAppTests | ||||
|             { | ||||
|                 cfg.AddBranch("a", d => | ||||
|                 { | ||||
|                     d.AddDelegate("b", _ => 0); | ||||
|                     d.AddDelegate("b", (_, _) => 0); | ||||
|                 }); | ||||
|             }); | ||||
|  | ||||
| @@ -1165,7 +1165,7 @@ public sealed partial class CommandAppTests | ||||
|             var app = new CommandAppTester(); | ||||
|             app.Configure(cfg => | ||||
|             { | ||||
|                 cfg.AddDelegate("a", _ => 0); | ||||
|                 cfg.AddDelegate("a", (_, _) => 0); | ||||
|             }); | ||||
|  | ||||
|             // When | ||||
| @@ -1189,7 +1189,7 @@ public sealed partial class CommandAppTests | ||||
|             { | ||||
|                 config.PropagateExceptions(); | ||||
|                 config.AddAsyncDelegate<DogSettings>( | ||||
|                     "foo", (context, settings) => | ||||
|                     "foo", (context, settings, _) => | ||||
|                     { | ||||
|                         dog = settings; | ||||
|                         data = (int)context.Data; | ||||
| @@ -1222,7 +1222,7 @@ public sealed partial class CommandAppTests | ||||
|                 config.AddBranch<AnimalSettings>("foo", foo => | ||||
|                 { | ||||
|                     foo.AddDelegate<DogSettings>( | ||||
|                         "bar", (context, settings) => | ||||
|                         "bar", (context, settings, _) => | ||||
|                         { | ||||
|                             dog = settings; | ||||
|                             data = (int)context.Data; | ||||
| @@ -1256,7 +1256,7 @@ public sealed partial class CommandAppTests | ||||
|                 config.AddBranch<AnimalSettings>("foo", foo => | ||||
|                 { | ||||
|                     foo.AddAsyncDelegate<DogSettings>( | ||||
|                         "bar", (context, settings) => | ||||
|                         "bar", (context, settings, _) => | ||||
|                         { | ||||
|                             dog = settings; | ||||
|                             data = (int)context.Data; | ||||
|   | ||||
| @@ -14,7 +14,7 @@ public sealed class CommandAppTesterTests | ||||
|             _console = console; | ||||
|         } | ||||
|  | ||||
|         public override int Execute(CommandContext context, OptionalArgumentWithDefaultValueSettings settings) | ||||
|         public override int Execute(CommandContext context, OptionalArgumentWithDefaultValueSettings settings, CancellationToken cancellationToken) | ||||
|         { | ||||
|             _console.Write(settings.Greeting); | ||||
|             return 0; | ||||
|   | ||||
| @@ -11,7 +11,7 @@ public sealed class InteractiveCommandTests | ||||
|             _console = console; | ||||
|         } | ||||
|  | ||||
|         public override int Execute(CommandContext context) | ||||
|         public override int Execute(CommandContext context, CancellationToken cancellationToken) | ||||
|         { | ||||
|             var fruits = _console.Prompt( | ||||
|                 new MultiSelectionPrompt<string>() | ||||
|   | ||||
		Reference in New Issue
	
	Block a user