Remove some public methods to avoid testing them

This commit is contained in:
Alexey Golub
2019-07-26 15:56:17 +03:00
parent 4e9effe481
commit c1ee1a968a
5 changed files with 79 additions and 91 deletions

View File

@@ -51,6 +51,28 @@ namespace CliFx
{
}
private IReadOnlyList<CommandSchema> GetAvailableCommandSchemas() =>
_commandTypes.Select(_commandSchemaResolver.GetCommandSchema).ToArray();
private CommandSchema GetMatchingCommandSchema(IReadOnlyList<CommandSchema> availableCommandSchemas, string commandName) =>
availableCommandSchemas.FirstOrDefault(c => string.Equals(c.Name, commandName, StringComparison.OrdinalIgnoreCase));
private bool IsHelpRequested(CommandInput commandInput)
{
var firstOptionAlias = commandInput.Options.FirstOrDefault()?.Alias;
return string.Equals(firstOptionAlias, "help", StringComparison.OrdinalIgnoreCase) ||
string.Equals(firstOptionAlias, "h", StringComparison.OrdinalIgnoreCase) ||
string.Equals(firstOptionAlias, "?", StringComparison.OrdinalIgnoreCase);
}
private bool IsVersionRequested(CommandInput commandInput)
{
var firstOptionAlias = commandInput.Options.FirstOrDefault()?.Alias;
return string.Equals(firstOptionAlias, "version", StringComparison.OrdinalIgnoreCase);
}
public async Task<int> RunAsync(IReadOnlyList<string> commandLineArguments)
{
var stdOut = ConsoleWriter.GetStandardOutput();
@@ -60,8 +82,8 @@ namespace CliFx
{
var commandInput = _commandInputParser.ParseInput(commandLineArguments);
var availableCommandSchemas = _commandSchemaResolver.GetCommandSchemas(_commandTypes);
var matchingCommandSchema = availableCommandSchemas.FindByNameOrNull(commandInput.CommandName);
var availableCommandSchemas = GetAvailableCommandSchemas();
var matchingCommandSchema = GetMatchingCommandSchema(availableCommandSchemas, commandInput.CommandName);
// Fail if there are no commands defined
if (!availableCommandSchemas.Any())
@@ -71,7 +93,7 @@ namespace CliFx
}
// Fail if specified a command which is not defined
if (commandInput.IsCommandSpecified() && matchingCommandSchema == null)
if (!commandInput.CommandName.IsNullOrWhiteSpace() && matchingCommandSchema == null)
{
stdErr.WriteLine($"Specified command [{commandInput.CommandName}] is not defined.");
return -1;
@@ -84,14 +106,14 @@ namespace CliFx
}
// Show version if it was requested without specifying a command
if (commandInput.IsVersionRequested() && !commandInput.IsCommandSpecified())
if (IsVersionRequested(commandInput) && commandInput.CommandName.IsNullOrWhiteSpace())
{
stdOut.WriteLine(_applicationMetadata.VersionText);
return 0;
}
// Show help if it was requested
if (commandInput.IsHelpRequested())
if (IsHelpRequested(commandInput))
{
var helpText = _commandHelpTextBuilder.Build(_applicationMetadata, availableCommandSchemas, matchingCommandSchema);
stdOut.WriteLine(helpText);

View File

@@ -1,72 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using CliFx.Internal;
namespace CliFx.Models
{
public static class Extensions
{
public static bool IsCommandSpecified(this CommandInput commandInput) => !commandInput.CommandName.IsNullOrWhiteSpace();
public static bool IsEmpty(this CommandInput commandInput) => !commandInput.IsCommandSpecified() && !commandInput.Options.Any();
public static bool IsHelpOption(this CommandOptionInput optionInput) =>
string.Equals(optionInput.Alias, "help", StringComparison.OrdinalIgnoreCase) ||
string.Equals(optionInput.Alias, "h", StringComparison.OrdinalIgnoreCase) ||
string.Equals(optionInput.Alias, "?", StringComparison.OrdinalIgnoreCase);
public static bool IsVersionOption(this CommandOptionInput optionInput) =>
string.Equals(optionInput.Alias, "version", StringComparison.OrdinalIgnoreCase);
public static bool IsHelpRequested(this CommandInput commandInput) => commandInput.Options.Any(o => o.IsHelpOption());
public static bool IsVersionRequested(this CommandInput commandInput) => commandInput.Options.Any(o => o.IsVersionOption());
public static bool IsDefault(this CommandSchema commandSchema) => commandSchema.Name.IsNullOrWhiteSpace();
public static CommandSchema FindByNameOrNull(this IEnumerable<CommandSchema> commandSchemas, string name) =>
commandSchemas.FirstOrDefault(c => string.Equals(c.Name, name, StringComparison.OrdinalIgnoreCase));
public static IReadOnlyList<CommandSchema> FindSubCommandSchemas(this IEnumerable<CommandSchema> commandSchemas,
string parentName)
{
// For a command with no name, every other command is its subcommand
if (parentName.IsNullOrWhiteSpace())
return commandSchemas.Where(c => !c.Name.IsNullOrWhiteSpace()).ToArray();
// For a named command, commands that are prefixed by its name are its subcommands
return commandSchemas.Where(c => !c.Name.IsNullOrWhiteSpace())
.Where(c => c.Name.StartsWith(parentName + " ", StringComparison.OrdinalIgnoreCase))
.ToArray();
}
public static CommandOptionSchema FindByAliasOrNull(this IEnumerable<CommandOptionSchema> optionSchemas, string alias) =>
optionSchemas.FirstOrDefault(o => o.GetAliases().Contains(alias, StringComparer.OrdinalIgnoreCase));
public static IReadOnlyList<string> GetAliases(this CommandOptionSchema optionSchema)
{
var result = new List<string>();
if (!optionSchema.Name.IsNullOrWhiteSpace())
result.Add(optionSchema.Name);
if (optionSchema.ShortName != null)
result.Add(optionSchema.ShortName.Value.AsString());
return result;
}
public static IReadOnlyList<string> GetAliasesWithPrefixes(this CommandOptionSchema optionSchema)
{
var result = new List<string>();
if (!optionSchema.Name.IsNullOrWhiteSpace())
result.Add("--" + optionSchema.Name);
if (optionSchema.ShortName != null)
result.Add("-" + optionSchema.ShortName.Value.AsString());
return result;
}
}
}

View File

@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using CliFx.Internal;
@@ -9,6 +10,29 @@ namespace CliFx.Services
// TODO: add color
public class CommandHelpTextBuilder : ICommandHelpTextBuilder
{
private IReadOnlyList<string> GetOptionAliasesWithPrefixes(CommandOptionSchema optionSchema)
{
var result = new List<string>();
if (!optionSchema.Name.IsNullOrWhiteSpace())
result.Add("--" + optionSchema.Name);
if (optionSchema.ShortName != null)
result.Add("-" + optionSchema.ShortName.Value);
return result;
}
private IReadOnlyList<CommandSchema> GetChildCommandSchemas(IReadOnlyList<CommandSchema> availableCommandSchemas,
CommandSchema parentCommandSchema)
{
// TODO: this doesn't really work properly, it shows all descendants instead of direct children
var prefix = !parentCommandSchema.Name.IsNullOrWhiteSpace() ? parentCommandSchema.Name + " " : "";
return availableCommandSchemas
.Where(c => !c.Name.IsNullOrWhiteSpace() && c.Name.StartsWith(prefix, StringComparison.OrdinalIgnoreCase)).ToArray();
}
private void AddDescription(StringBuilder buffer, CommandSchema commands)
{
if (commands.Description.IsNullOrWhiteSpace())
@@ -56,7 +80,7 @@ namespace CliFx.Services
{
buffer.Append(option.IsRequired ? "* " : " ");
buffer.Append(option.GetAliasesWithPrefixes().JoinToString("|"));
buffer.Append(GetOptionAliasesWithPrefixes(option).JoinToString("|"));
if (!option.Description.IsNullOrWhiteSpace())
{
@@ -77,7 +101,7 @@ namespace CliFx.Services
}
// Version option
if (command.IsDefault())
if (command.Name.IsNullOrWhiteSpace())
{
buffer.Append(" ");
buffer.Append("--version");
@@ -118,11 +142,11 @@ namespace CliFx.Services
IReadOnlyList<CommandSchema> availableCommandSchemas,
CommandSchema matchingCommandSchema)
{
var subCommands = availableCommandSchemas.FindSubCommandSchemas(matchingCommandSchema.Name);
var childCommandSchemas = GetChildCommandSchemas(availableCommandSchemas, matchingCommandSchema);
var buffer = new StringBuilder();
if (matchingCommandSchema.IsDefault())
if (matchingCommandSchema.Name.IsNullOrWhiteSpace())
{
buffer.Append(applicationMetadata.Title);
buffer.Append(" v");
@@ -131,11 +155,11 @@ namespace CliFx.Services
}
AddDescription(buffer, matchingCommandSchema);
AddUsage(buffer, applicationMetadata, matchingCommandSchema, subCommands);
AddUsage(buffer, applicationMetadata, matchingCommandSchema, childCommandSchemas);
AddOptions(buffer, matchingCommandSchema);
AddSubCommands(buffer, subCommands);
AddSubCommands(buffer, childCommandSchemas);
if (matchingCommandSchema.IsDefault() && subCommands.Any())
if (matchingCommandSchema.Name.IsNullOrWhiteSpace() && childCommandSchemas.Any())
{
buffer.Append("You can run ");
buffer.Append('`').Append(applicationMetadata.ExecutableName).Append(" [command] --help").Append('`');

View File

@@ -21,6 +21,25 @@ namespace CliFx.Services
{
}
private CommandOptionSchema GetMatchingOptionSchema(CommandSchema commandSchema, CommandOptionInput optionInput)
{
foreach (var optionSchema in commandSchema.Options)
{
var matchesByName =
!optionSchema.Name.IsNullOrWhiteSpace() &&
string.Equals(optionSchema.Name, optionInput.Alias, StringComparison.OrdinalIgnoreCase);
var matchesByShortName =
optionSchema.ShortName != null &&
string.Equals(optionSchema.ShortName.Value.AsString(), optionInput.Alias, StringComparison.OrdinalIgnoreCase);
if (matchesByName || matchesByShortName)
return optionSchema;
}
return null;
}
public void InitializeCommand(ICommand command, CommandSchema schema, CommandInput input)
{
// Set command options
@@ -29,7 +48,7 @@ namespace CliFx.Services
var properties = new HashSet<CommandOptionSchema>();
foreach (var option in input.Options)
{
var optionSchema = schema.Options.FindByAliasOrNull(option.Alias);
var optionSchema = GetMatchingOptionSchema(schema, option);
if (optionSchema == null)
continue;

View File

@@ -1,16 +1,11 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using CliFx.Models;
namespace CliFx.Services
{
public static class Extensions
{
public static IReadOnlyList<CommandSchema> GetCommandSchemas(this ICommandSchemaResolver commandSchemaResolver,
IEnumerable<Type> commandTypes) => commandTypes.Select(commandSchemaResolver.GetCommandSchema).ToArray();
public static void Write(this IConsoleWriter consoleWriter, string text) =>
consoleWriter.Write(new TextSpan(text));