From 4b98dbf51fc877e3c3bb6c3d228cd36d5efbd8a9 Mon Sep 17 00:00:00 2001 From: Alexey Golub Date: Mon, 19 Aug 2019 21:51:06 +0300 Subject: [PATCH] Refactor CommandInputParser --- CliFx/Models/Extensions.cs | 6 +++ CliFx/Services/CommandInputParser.cs | 71 ++++++++++------------------ CliFx/Services/Extensions.cs | 2 +- 3 files changed, 33 insertions(+), 46 deletions(-) diff --git a/CliFx/Models/Extensions.cs b/CliFx/Models/Extensions.cs index e8eefcd..f406a8f 100644 --- a/CliFx/Models/Extensions.cs +++ b/CliFx/Models/Extensions.cs @@ -16,6 +16,12 @@ namespace CliFx.Models public static CommandSchema FindByName(this IReadOnlyList commandSchemas, string commandName) { commandSchemas.GuardNotNull(nameof(commandSchemas)); + + // If looking for default command, don't compare names directly + // ...because null and empty are both valid names for default command + if (commandName.IsNullOrWhiteSpace()) + return commandSchemas.FirstOrDefault(c => c.IsDefault()); + return commandSchemas.FirstOrDefault(c => string.Equals(c.Name, commandName, StringComparison.OrdinalIgnoreCase)); } diff --git a/CliFx/Services/CommandInputParser.cs b/CliFx/Services/CommandInputParser.cs index b073812..387fa97 100644 --- a/CliFx/Services/CommandInputParser.cs +++ b/CliFx/Services/CommandInputParser.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Text; using CliFx.Internal; using CliFx.Models; @@ -16,75 +17,55 @@ namespace CliFx.Services { commandLineArguments.GuardNotNull(nameof(commandLineArguments)); - // Initialize command name placeholder - string commandName = null; + var commandNameBuilder = new StringBuilder(); + var optionsDic = new Dictionary>(); - // Initialize options - var rawOptions = new Dictionary>(); + var lastOptionAlias = ""; - // Keep track of the last option's name - string optionName = null; - - // Loop through all arguments - var encounteredFirstOption = false; foreach (var commandLineArgument in commandLineArguments) { - // Option name + // Encountered option name if (commandLineArgument.StartsWith("--", StringComparison.OrdinalIgnoreCase)) { - // Extract option name (skip 2 chars) - optionName = commandLineArgument.Substring(2); + // Extract option alias + lastOptionAlias = commandLineArgument.Substring(2); - if (rawOptions.GetValueOrDefault(optionName) == null) - rawOptions[optionName] = new List(); - - encounteredFirstOption = true; + if (!optionsDic.ContainsKey(lastOptionAlias)) + optionsDic[lastOptionAlias] = new List(); } - // Short option name - else if (commandLineArgument.StartsWith("-", StringComparison.OrdinalIgnoreCase) && commandLineArgument.Length == 2) - { - // Extract option name (skip 1 char) - optionName = commandLineArgument.Substring(1); - - if (rawOptions.GetValueOrDefault(optionName) == null) - rawOptions[optionName] = new List(); - - encounteredFirstOption = true; - } - - // Multiple stacked short options + // Encountered short option name or multiple thereof else if (commandLineArgument.StartsWith("-", StringComparison.OrdinalIgnoreCase)) { + // Handle stacked options foreach (var c in commandLineArgument.Substring(1)) { - optionName = c.AsString(); + // Extract option alias + lastOptionAlias = c.AsString(); - if (rawOptions.GetValueOrDefault(optionName) == null) - rawOptions[optionName] = new List(); + if (!optionsDic.ContainsKey(lastOptionAlias)) + optionsDic[lastOptionAlias] = new List(); } - - encounteredFirstOption = true; } - // Command name - else if (!encounteredFirstOption) + // Encountered command name or part thereof + else if (lastOptionAlias.IsNullOrWhiteSpace()) { - if (commandName.IsNullOrWhiteSpace()) - commandName = commandLineArgument; - else - commandName += " " + commandLineArgument; + commandNameBuilder.AppendIfNotEmpty(' '); + commandNameBuilder.Append(commandLineArgument); } - // Option value - else if (!optionName.IsNullOrWhiteSpace()) + // Encountered option value + else if (!lastOptionAlias.IsNullOrWhiteSpace()) { - // ReSharper disable once AssignNullToNotNullAttribute - rawOptions[optionName].Add(commandLineArgument); + optionsDic[lastOptionAlias].Add(commandLineArgument); } } - return new CommandInput(commandName, rawOptions.Select(p => new CommandOptionInput(p.Key, p.Value)).ToArray()); + var commandName = commandNameBuilder.Length > 0 ? commandNameBuilder.ToString() : null; + var options = optionsDic.Select(p => new CommandOptionInput(p.Key, p.Value)).ToArray(); + + return new CommandInput(commandName, options); } } } \ No newline at end of file diff --git a/CliFx/Services/Extensions.cs b/CliFx/Services/Extensions.cs index 9e37175..5eef06d 100644 --- a/CliFx/Services/Extensions.cs +++ b/CliFx/Services/Extensions.cs @@ -18,7 +18,7 @@ namespace CliFx.Services resolver.GuardNotNull(nameof(resolver)); commandType.GuardNotNull(nameof(commandType)); - return resolver.GetCommandSchemas(new[] {commandType}).First(); + return resolver.GetCommandSchemas(new[] {commandType}).Single(); } ///