Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.IO;
using System.Threading;
using Generator.Models;
using Scriban;
using Spectre.Console.Cli;
Expand All @@ -21,7 +22,7 @@ public sealed class Settings : GeneratorSettings
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[]
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using AngleSharp.Html.Parser;
using Generator.Models;
Expand Down Expand Up @@ -39,7 +40,7 @@ public EmojiGeneratorCommand()
_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))
Expand Down
3 changes: 2 additions & 1 deletion resources/scripts/Generator/Commands/SampleCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using Generator.Commands.Samples;
using Spectre.Console;
using Spectre.Console.Cli;
Expand Down Expand Up @@ -38,7 +39,7 @@ public SampleCommand(IAnsiConsole console)
_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()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System.Collections.Generic;
using System.IO;
using System.Threading;
using Generator.Models;
using Scriban;
using Spectre.Console.Cli;
Expand All @@ -16,7 +17,7 @@ public SpinnerGeneratorCommand()
_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>();
Expand Down
7 changes: 5 additions & 2 deletions src/.editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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
11 changes: 6 additions & 5 deletions src/Spectre.Console.Cli/AsyncCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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/>
Expand Down
11 changes: 6 additions & 5 deletions src/Spectre.Console.Cli/AsyncCommandOfT.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,9 @@ public virtual ValidationResult Validate(CommandContext context, TSettings setti
/// </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)
Expand All @@ -33,15 +34,15 @@ ValidationResult ICommand.Validate(CommandContext context, CommandSettings setti
}

/// <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);
}
}
11 changes: 6 additions & 5 deletions src/Spectre.Console.Cli/Command.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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/>
Expand Down
30 changes: 12 additions & 18 deletions src/Spectre.Console.Cli/CommandApp.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,7 @@ public CommandApp(ITypeRegistrar? registrar = null)
_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)
Expand All @@ -51,22 +48,14 @@ public DefaultCommandConfigurator SetDefaultCommand<TCommand>()
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
{
Expand All @@ -86,7 +75,7 @@ public async Task<int> RunAsync(IEnumerable<string> args)
}

return await _executor
.Execute(_configurator, args)
.ExecuteAsync(_configurator, args, cancellationToken)
.ConfigureAwait(false);
}
catch (Exception ex)
Expand All @@ -109,6 +98,11 @@ public async Task<int> RunAsync(IEnumerable<string> args)
return _configurator.Settings.ExceptionHandler(ex, null);
}

if (ex is OperationCanceledException)
{
return _configurator.Settings.CancellationExitCode;
}

// Render the exception.
var pretty = GetRenderableErrorMessage(ex);
if (pretty != null)
Expand Down
25 changes: 7 additions & 18 deletions src/Spectre.Console.Cli/CommandAppOfT.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,33 +25,22 @@ public CommandApp(ITypeRegistrar? registrar = null)
_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()
Expand Down
11 changes: 6 additions & 5 deletions src/Spectre.Console.Cli/CommandOfT.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,9 @@ public virtual ValidationResult Validate(CommandContext context, TSettings setti
/// </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)
Expand All @@ -34,15 +35,15 @@ ValidationResult ICommand.Validate(CommandContext context, CommandSettings setti
}

/// <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));
}
}
34 changes: 26 additions & 8 deletions src/Spectre.Console.Cli/ConfiguratorExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,24 @@ public static IConfigurator PropagateExceptions(this IConfigurator configurator)
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>
Expand Down Expand Up @@ -304,14 +322,14 @@ public static IBranchConfigurator AddBranch<TSettings>(
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>
Expand All @@ -324,14 +342,14 @@ public static ICommandConfigurator AddDelegate(
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>
Expand All @@ -345,7 +363,7 @@ public static ICommandConfigurator AddAsyncDelegate(
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)
Expand All @@ -358,7 +376,7 @@ public static ICommandConfigurator AddDelegate<TSettings>(
throw new ArgumentNullException(nameof(configurator));
}

return configurator.AddDelegate<TSettings>(name, (c, _) => func(c));
return configurator.AddDelegate<TSettings>(name, (c, _, ct) => func(c, ct));
}

/// <summary>
Expand All @@ -372,15 +390,15 @@ public static ICommandConfigurator AddDelegate<TSettings>(
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)
{
throw new ArgumentNullException(nameof(configurator));
}

return configurator.AddAsyncDelegate<TSettings>(name, (c, _) => func(c));
return configurator.AddAsyncDelegate<TSettings>(name, (c, _, ct) => func(c, ct));
}

/// <summary>
Expand Down
Loading