From 41760095d4b634f3bf679be2c0411ceb55c2d6e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lew=20Szyma=C5=84ski?= Date: Tue, 13 Aug 2024 20:50:04 +0200 Subject: [PATCH] fixed issues with IsFallbackRequested (and renamed it to ExecutedAsDefaultCommand) --- .../Bindings/BackwardCompatibility.cs | 6 +++--- source/ECF.Tests/Bindings/BaseBinding.cs | 6 +++--- source/ECF.Tests/Bindings/NullableBindings.cs | 4 ++-- .../Bindings/RequiredPropertiesBinding.cs | 8 +++---- .../Bindings/StringComparisonTests.cs | 4 ++-- source/ECF/BaseKit/Commands/HelpCommand.cs | 11 ++++++---- source/ECF/Engine/CancellationController.cs | 4 ++-- source/ECF/Engine/CommandProcessor.cs | 21 +++++-------------- source/ECF/Engine/Models/CommandArguments.cs | 16 ++++++++------ source/ECF/Utilities/CommandDispatcher.cs | 7 +------ 10 files changed, 39 insertions(+), 48 deletions(-) diff --git a/source/ECF.Tests/Bindings/BackwardCompatibility.cs b/source/ECF.Tests/Bindings/BackwardCompatibility.cs index 5a72343..138d43b 100644 --- a/source/ECF.Tests/Bindings/BackwardCompatibility.cs +++ b/source/ECF.Tests/Bindings/BackwardCompatibility.cs @@ -11,7 +11,7 @@ public void all_new_bindings_works() var args = "first second third -f1 -f2 f3 -p1 fourth -p2 fifth p3 sixth".Tokenize(); - command.ApplyArguments(new CommandArguments(null, args)); + command.ApplyArguments(CommandArguments.FromCode(args)); Assert.Equal("first", command.Argument1); Assert.Equal("second", command.Argument2); @@ -33,7 +33,7 @@ public void all_old_bindings_works() var args = "first second third -cf1 -cf2 -cf3 -cp1 fourth -cp2 fifth -cp3 sixth".Tokenize(); - command.ApplyArguments(new CommandArguments(null, args)); + command.ApplyArguments(CommandArguments.FromCode(args)); Assert.Equal("first", command.CmdArgument1); Assert.Equal("second", command.CmdArgument2); @@ -59,7 +59,7 @@ public void priorize_new_bindings_over_old_ones() var args = "first -second third".Tokenize(); - command.ApplyArguments(new CommandArguments(null, args)); + command.ApplyArguments(CommandArguments.FromCode(args)); Assert.Equal("first", command.Argument1); Assert.Null(command.Argument2); diff --git a/source/ECF.Tests/Bindings/BaseBinding.cs b/source/ECF.Tests/Bindings/BaseBinding.cs index 1d49bba..8d74f85 100644 --- a/source/ECF.Tests/Bindings/BaseBinding.cs +++ b/source/ECF.Tests/Bindings/BaseBinding.cs @@ -11,7 +11,7 @@ public void arguments_in_right_order() var args = "first second third fourth fifth -f1 -f2 -f3".Tokenize(); - command.ApplyArguments(new CommandArguments(null, args)); + command.ApplyArguments(CommandArguments.FromCode(args)); Assert.Equal("first", command.Argument1); Assert.Equal("second", command.Argument2); @@ -25,7 +25,7 @@ public void avoid_binding_by_accident_another_flag() var args = "justtoignorefistargument -p1 -p2 test".Tokenize(); - command.ApplyArguments(new CommandArguments(null, args)); + command.ApplyArguments(CommandArguments.FromCode(args)); Assert.Null(command.Parameter1); Assert.Equal("test", command.Parameter2); @@ -44,7 +44,7 @@ public void bonus_tests(string input, string? argument1, string? argument2, stri var args = input.Tokenize(); - command.ApplyArguments(new CommandArguments(null, args)); + command.ApplyArguments(CommandArguments.FromCode(args)); // new bindings Assert.Equal(argument1, command.Argument1); diff --git a/source/ECF.Tests/Bindings/NullableBindings.cs b/source/ECF.Tests/Bindings/NullableBindings.cs index 1f9e3a6..81ee6d7 100644 --- a/source/ECF.Tests/Bindings/NullableBindings.cs +++ b/source/ECF.Tests/Bindings/NullableBindings.cs @@ -9,7 +9,7 @@ public void assigning_nullable_and_nonnulable_works_same() var args = "134 \"7820\"".Tokenize(); - command.ApplyArguments(new CommandArguments(null, args)); + command.ApplyArguments(CommandArguments.FromCode(args)); Assert.Equal(134, command.NonNullableProperty); Assert.Equal(7820, command.NullableProperty); @@ -20,7 +20,7 @@ public void defaults_working_as_intended() { NullableCommand command = new(); - command.ApplyArguments(new CommandArguments(null, [])); + command.ApplyArguments(CommandArguments.FromCode([])); Assert.Equal(0, command.NonNullableProperty); Assert.Null(command.NullableProperty); diff --git a/source/ECF.Tests/Bindings/RequiredPropertiesBinding.cs b/source/ECF.Tests/Bindings/RequiredPropertiesBinding.cs index 63f7011..8660dc6 100644 --- a/source/ECF.Tests/Bindings/RequiredPropertiesBinding.cs +++ b/source/ECF.Tests/Bindings/RequiredPropertiesBinding.cs @@ -11,7 +11,7 @@ public void empty_should_return_false_in_Validate() var args = new string[0]; - command.ApplyArguments(new CommandArguments(null, args)); + command.ApplyArguments(CommandArguments.FromCode(args)); Assert.False(command.Validate(out var errors)); @@ -28,7 +28,7 @@ public void only_one_required_supplied_should_return_false_in_Validate() var args = "first".Tokenize(); - command.ApplyArguments(new CommandArguments(null, args)); + command.ApplyArguments(CommandArguments.FromCode(args)); Assert.False(command.Validate(out var errors)); @@ -45,7 +45,7 @@ public void minimum_supplied_should_return_true_in_Validate() var args = "first --required-param test".Tokenize(); - command.ApplyArguments(new CommandArguments(null, args)); + command.ApplyArguments(CommandArguments.FromCode(args)); Assert.True(command.Validate(out var errors)); @@ -59,7 +59,7 @@ public void full_supplied_should_return_true_in_Validate() var args = "first second --required-param test --non-required-param test".Tokenize(); - command.ApplyArguments(new CommandArguments(null, args)); + command.ApplyArguments(CommandArguments.FromCode(args)); Assert.True(command.Validate(out var errors)); Assert.Empty(errors); diff --git a/source/ECF.Tests/Bindings/StringComparisonTests.cs b/source/ECF.Tests/Bindings/StringComparisonTests.cs index 0fc2c2d..a91d6ce 100644 --- a/source/ECF.Tests/Bindings/StringComparisonTests.cs +++ b/source/ECF.Tests/Bindings/StringComparisonTests.cs @@ -11,7 +11,7 @@ public void case_sensitive_tests() var args = "-f1 -F2 f3 -p1 test -P2 test p3 test -cf1 -cF2 -cf3 -cp1 test -CP2 test -cp3 test".Tokenize(); - command.ApplyArguments(new CommandArguments(null, args)); + command.ApplyArguments(CommandArguments.FromCode(args)); Assert.True(command.Flag1); Assert.False(command.Flag2); @@ -37,7 +37,7 @@ public void case_insensitive_tests() var args = "-f1 -F2 f3 -p1 test -P2 test p3 test".Tokenize(); - command.ApplyArguments(new CommandArguments(null, args)); + command.ApplyArguments(CommandArguments.FromCode(args)); Assert.True(command.Flag1); Assert.True(command.Flag2); diff --git a/source/ECF/BaseKit/Commands/HelpCommand.cs b/source/ECF/BaseKit/Commands/HelpCommand.cs index b7e102b..2688393 100644 --- a/source/ECF/BaseKit/Commands/HelpCommand.cs +++ b/source/ECF/BaseKit/Commands/HelpCommand.cs @@ -22,13 +22,16 @@ public HelpCommand(ICommandResolver commandResolver, ICommandCollection commands public Task ExecuteAsync(CommandArguments args, CancellationToken _) { - if (args.IsFallbackRequested && string.IsNullOrWhiteSpace(args.CommandName) == false) // command with binding args.CommandName does not exits + bool isArgumentPresent = args.Arguments.Length > 0 + && string.IsNullOrWhiteSpace(args.Arguments[0]) == false; + + if (args.ExecutedAsDefaultCommand == false && isArgumentPresent) { - Console.WriteLine($"Command not found: {notFoundCommand}. Type 'help' to list commands."); + PrintHelpForSpecifiedCommand(args.Arguments[0]); } - else if (args.Arguments.Length > 0 && string.IsNullOrWhiteSpace(args.Arguments[0]) == false) // for example: help command-to-display-help + else if (isArgumentPresent) { - PrintHelpForSpecifiedCommand(args.Arguments[0]); + Console.WriteLine($"Command not found: {notFoundCommand}. Type 'help' to list commands."); } else { diff --git a/source/ECF/Engine/CancellationController.cs b/source/ECF/Engine/CancellationController.cs index 03794fd..2289056 100644 --- a/source/ECF/Engine/CancellationController.cs +++ b/source/ECF/Engine/CancellationController.cs @@ -25,12 +25,12 @@ private void Console_CancelKeyPress(object? sender, ConsoleCancelEventArgs e) { if (singleCommandSource == null) { - e.Cancel = true; // Prevent the process from terminating immediately + e.Cancel = true; // Prevent the process from terminating rootSource.Cancel(); } else if (singleCommandSource != null && singleCommandSource.IsCancellationRequested == false) { - e.Cancel = true; // Prevent the process from terminating immediately + e.Cancel = true; // Prevent the process from terminating singleCommandSource.Cancel(); ColorConsole.WriteLine("Cancellation requested. Press again ctrl+c to force shutdown.", ConsoleColor.Yellow); } diff --git a/source/ECF/Engine/CommandProcessor.cs b/source/ECF/Engine/CommandProcessor.cs index 0c58095..47fd5f9 100644 --- a/source/ECF/Engine/CommandProcessor.cs +++ b/source/ECF/Engine/CommandProcessor.cs @@ -32,30 +32,19 @@ public async Task ProcessAsync(string[] args, CancellationToken ct) var resolver = scope.Resolve(); var context = scope.Resolve(); - ICommand? command; - CommandArguments arguments; + ICommand? command = null; + CommandArguments? arguments = null; if (args.Length > 0) { command = resolver.Resolve(args[0]); - arguments = new CommandArguments( - commandName: args[0], - arguments: args.Skip(1).ToArray() - ); - } - else - { - command = null; - arguments = new CommandArguments( - commandName: null, - arguments: args ?? new string[0] - ); + arguments = CommandArguments.ForMappedCommand(args[0], args.Skip(1).ToArray()); } if (command == null && context.DefaultCommand != null) { command = resolver.Resolve(context.DefaultCommand); - arguments.IsFallbackRequested = true; + arguments = CommandArguments.ForDefaultCommand(args); } if (command == null) @@ -63,7 +52,7 @@ public async Task ProcessAsync(string[] args, CancellationToken ct) throw new CommandNotFoundException(args ?? new string[0]); } - await command.ExecuteAsync(arguments, ct); + await command.ExecuteAsync(arguments!, ct); } } } \ No newline at end of file diff --git a/source/ECF/Engine/Models/CommandArguments.cs b/source/ECF/Engine/Models/CommandArguments.cs index afdabb9..7b60ad8 100644 --- a/source/ECF/Engine/Models/CommandArguments.cs +++ b/source/ECF/Engine/Models/CommandArguments.cs @@ -5,22 +5,26 @@ public class CommandArguments /// /// Command name or alias passed by user. It can be null if used as a default command, or used from dispatcher. /// - public string? CommandName { get; set; } + public string? CommandName { get; init; } /// /// Arguments passed by user (if first argument was not recognized as command name this will included here) /// - public string[] Arguments { get; set; } + public string[] Arguments { get; init; } /// - /// This is special flag that is set to true if command was not found and fallback command is being executed + /// Set to true if command was not found and fallback command is being executed, or when no arguments were passed. /// - public bool IsFallbackRequested { get; set; } + public bool ExecutedAsDefaultCommand { get; init; } - public CommandArguments(string? commandName, string[] arguments, bool isFallbackRequested = false) + private CommandArguments(string? commandName, string[] arguments) { CommandName = commandName; Arguments = arguments; - IsFallbackRequested = isFallbackRequested; } + + public static CommandArguments Empty() => new CommandArguments(null, new string[0]); + public static CommandArguments ForMappedCommand(string commandName, string[] arguments) => new CommandArguments(commandName, arguments); + public static CommandArguments FromCode(string[] arguments) => new CommandArguments(null, arguments); + public static CommandArguments ForDefaultCommand(string[] arguments) => new CommandArguments(null, arguments) { ExecutedAsDefaultCommand = true }; } diff --git a/source/ECF/Utilities/CommandDispatcher.cs b/source/ECF/Utilities/CommandDispatcher.cs index 7fab5e8..9b3335c 100644 --- a/source/ECF/Utilities/CommandDispatcher.cs +++ b/source/ECF/Utilities/CommandDispatcher.cs @@ -18,12 +18,7 @@ public async Task ExecuteCommandAsync(string[] commandArgs, CancellationToken using (var nestedScope = iocProvider.BeginNestedScope()) { var command = nestedScope.Resolve(); - CommandArguments args = new( - commandName: null, - arguments: commandArgs, - isFallbackRequested: false - ); - await command.ExecuteAsync(args, cancellationToken); + await command.ExecuteAsync(CommandArguments.FromCode(commandArgs), cancellationToken); } } }