mirror of
https://github.com/Tyrrrz/CliFx.git
synced 2025-10-25 15:19:17 +00:00
Refactor
This commit is contained in:
@@ -39,10 +39,15 @@ namespace CliFx
|
||||
_commandHelpTextRenderer = commandHelpTextRenderer;
|
||||
}
|
||||
|
||||
public CliApplication(ApplicationMetadata applicationMetadata, IReadOnlyList<Type> commandTypes)
|
||||
public CliApplication(ApplicationMetadata applicationMetadata, IReadOnlyList<Type> commandTypes, IConsole console)
|
||||
: this(applicationMetadata, commandTypes,
|
||||
new SystemConsole(), new CommandInputParser(), new CommandSchemaResolver(),
|
||||
new CommandFactory(), new CommandInitializer(), new CommandHelpTextRenderer())
|
||||
console, new CommandInputParser(), new CommandSchemaResolver(),
|
||||
new CommandFactory(), new CommandInitializer(), new CommandHelpTextRenderer(console))
|
||||
{
|
||||
}
|
||||
|
||||
public CliApplication(ApplicationMetadata applicationMetadata, IReadOnlyList<Type> commandTypes)
|
||||
: this(applicationMetadata, commandTypes, new SystemConsole())
|
||||
{
|
||||
}
|
||||
|
||||
@@ -56,22 +61,14 @@ 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));
|
||||
|
||||
|
||||
|
||||
public async Task<int> RunAsync(IReadOnlyList<string> commandLineArguments)
|
||||
{
|
||||
try
|
||||
{
|
||||
var commandInput = _commandInputParser.ParseInput(commandLineArguments);
|
||||
|
||||
var availableCommandSchemas = GetAvailableCommandSchemas();
|
||||
var matchingCommandSchema = GetMatchingCommandSchema(availableCommandSchemas, commandInput.CommandName);
|
||||
var availableCommandSchemas = _commandSchemaResolver.GetCommandSchemas(_commandTypes);
|
||||
var matchingCommandSchema = availableCommandSchemas.FindByName(commandInput.CommandName);
|
||||
|
||||
// Fail if there are no commands defined
|
||||
if (!availableCommandSchemas.Any())
|
||||
@@ -85,27 +82,31 @@ namespace CliFx
|
||||
// Handle cases where requested command is not defined
|
||||
if (matchingCommandSchema == null)
|
||||
{
|
||||
var isError = false;
|
||||
|
||||
// If specified a command - show error
|
||||
if (commandInput.IsCommandSpecified())
|
||||
{
|
||||
isError = true;
|
||||
|
||||
_console.WithColor(ConsoleColor.Red,
|
||||
c => c.Error.WriteLine($"Specified command [{commandInput.CommandName}] is not defined."));
|
||||
}
|
||||
|
||||
// Get default command schema
|
||||
var defaultCommandSchema = availableCommandSchemas.FirstOrDefault(c => c.IsDefault());
|
||||
// Get parent command schema
|
||||
var parentCommandSchema = availableCommandSchemas.FindParent(commandInput.CommandName);
|
||||
|
||||
// Use a stub if default command schema is not defined
|
||||
if (defaultCommandSchema == null)
|
||||
// Use a stub if parent command schema is not found
|
||||
if (parentCommandSchema == null)
|
||||
{
|
||||
defaultCommandSchema = _commandSchemaResolver.GetCommandSchema(typeof(StubDefaultCommand));
|
||||
availableCommandSchemas = availableCommandSchemas.Concat(new[] {defaultCommandSchema}).ToArray();
|
||||
parentCommandSchema = _commandSchemaResolver.GetCommandSchema(typeof(StubDefaultCommand));
|
||||
availableCommandSchemas = availableCommandSchemas.Concat(new[] { parentCommandSchema }).ToArray();
|
||||
}
|
||||
|
||||
// Show help
|
||||
_commandHelpTextRenderer.RenderHelpText(_applicationMetadata, availableCommandSchemas, defaultCommandSchema);
|
||||
_commandHelpTextRenderer.RenderHelpText(_applicationMetadata, availableCommandSchemas, parentCommandSchema);
|
||||
|
||||
return commandInput.IsCommandSpecified() ? -1 : 0;
|
||||
return isError ? -1 : 0;
|
||||
}
|
||||
|
||||
// Show version if it was requested without specifying a command
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using CliFx.Internal;
|
||||
|
||||
@@ -25,5 +26,48 @@ namespace CliFx.Models
|
||||
}
|
||||
|
||||
public static bool IsDefault(this CommandSchema commandSchema) => commandSchema.Name.IsNullOrWhiteSpace();
|
||||
|
||||
public static CommandSchema FindByName(this IReadOnlyList<CommandSchema> commandSchemas, string commandName) =>
|
||||
commandSchemas.FirstOrDefault(c => string.Equals(c.Name, commandName, StringComparison.OrdinalIgnoreCase));
|
||||
|
||||
public static CommandSchema FindParent(this IReadOnlyList<CommandSchema> commandSchemas, string commandName)
|
||||
{
|
||||
// If command has no name, it's the default command so it doesn't have a parent
|
||||
if (commandName.IsNullOrWhiteSpace())
|
||||
return null;
|
||||
|
||||
// Repeatedly cut off individual words from the name until we find a command with that name
|
||||
var temp = commandName;
|
||||
while (temp.Contains(" "))
|
||||
{
|
||||
temp = temp.SubstringUntilLast(" ");
|
||||
|
||||
var parent = commandSchemas.FindByName(temp);
|
||||
if (parent != null)
|
||||
return parent;
|
||||
}
|
||||
|
||||
// If no parent is matched by name, then the parent is the default command
|
||||
return commandSchemas.FirstOrDefault(c => c.IsDefault());
|
||||
}
|
||||
|
||||
public static CommandOptionSchema FindByAlias(this IReadOnlyList<CommandOptionSchema> optionSchemas, string alias)
|
||||
{
|
||||
foreach (var optionSchema in optionSchemas)
|
||||
{
|
||||
var matchesByName =
|
||||
!optionSchema.Name.IsNullOrWhiteSpace() &&
|
||||
string.Equals(optionSchema.Name, alias, StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
var matchesByShortName =
|
||||
optionSchema.ShortName != null &&
|
||||
string.Equals(optionSchema.ShortName.Value.AsString(), alias, StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
if (matchesByName || matchesByShortName)
|
||||
return optionSchema;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using CliFx.Internal;
|
||||
using CliFx.Models;
|
||||
|
||||
@@ -16,11 +15,6 @@ namespace CliFx.Services
|
||||
_console = console;
|
||||
}
|
||||
|
||||
public CommandHelpTextRenderer()
|
||||
: this(new SystemConsole())
|
||||
{
|
||||
}
|
||||
|
||||
private void RenderDescription(CommandSchema commandSchema)
|
||||
{
|
||||
if (commandSchema.Description.IsNullOrWhiteSpace())
|
||||
@@ -170,7 +164,9 @@ namespace CliFx.Services
|
||||
public void RenderHelpText(ApplicationMetadata applicationMetadata,
|
||||
IReadOnlyList<CommandSchema> availableCommandSchemas, CommandSchema matchingCommandSchema)
|
||||
{
|
||||
var childCommandSchemas = GetChildCommandSchemas(availableCommandSchemas, matchingCommandSchema);
|
||||
var childCommandSchemas = availableCommandSchemas
|
||||
.Where(c => availableCommandSchemas.FindParent(c.Name) == matchingCommandSchema)
|
||||
.ToArray();
|
||||
|
||||
// Render application info
|
||||
if (matchingCommandSchema.IsDefault())
|
||||
@@ -191,48 +187,9 @@ namespace CliFx.Services
|
||||
|
||||
public partial class CommandHelpTextRenderer
|
||||
{
|
||||
private static CommandSchema GetParentOrNull(CommandSchema commandSchema, IReadOnlyList<CommandSchema> availableCommandSchemas)
|
||||
{
|
||||
if (commandSchema.IsDefault())
|
||||
return null;
|
||||
|
||||
var nameBuffer = commandSchema.Name;
|
||||
while (nameBuffer.Contains(' '))
|
||||
{
|
||||
nameBuffer = nameBuffer.SubstringUntilLast(" ");
|
||||
var parent = availableCommandSchemas.FirstOrDefault(c =>
|
||||
string.Equals(c.Name, nameBuffer, StringComparison.OrdinalIgnoreCase));
|
||||
|
||||
if (parent != null)
|
||||
return parent;
|
||||
}
|
||||
|
||||
return availableCommandSchemas.FirstOrDefault(c => c.IsDefault());
|
||||
}
|
||||
|
||||
private static IReadOnlyList<CommandSchema> GetChildCommandSchemas(IReadOnlyList<CommandSchema> availableCommandSchemas,
|
||||
CommandSchema parentCommandSchema)
|
||||
{
|
||||
var result = new List<CommandSchema>();
|
||||
|
||||
foreach (var commandSchema in availableCommandSchemas)
|
||||
{
|
||||
if (commandSchema == parentCommandSchema)
|
||||
continue;
|
||||
|
||||
if (GetParentOrNull(commandSchema, availableCommandSchemas) == parentCommandSchema)
|
||||
result.Add(commandSchema);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static string GetRelativeCommandName(CommandSchema commandSchema, CommandSchema parentCommandSchema)
|
||||
{
|
||||
if (parentCommandSchema.Name.IsNullOrWhiteSpace())
|
||||
return commandSchema.Name;
|
||||
|
||||
return commandSchema.Name.Substring(parentCommandSchema.Name.Length + 1);
|
||||
}
|
||||
private static string GetRelativeCommandName(CommandSchema commandSchema, CommandSchema parentCommandSchema) =>
|
||||
parentCommandSchema.Name.IsNullOrWhiteSpace()
|
||||
? commandSchema.Name
|
||||
: commandSchema.Name.Substring(parentCommandSchema.Name.Length + 1);
|
||||
}
|
||||
}
|
||||
@@ -21,25 +21,6 @@ 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
|
||||
@@ -48,7 +29,7 @@ namespace CliFx.Services
|
||||
var properties = new HashSet<CommandOptionSchema>();
|
||||
foreach (var option in input.Options)
|
||||
{
|
||||
var optionSchema = GetMatchingOptionSchema(schema, option);
|
||||
var optionSchema = schema.Options.FindByAlias(option.Alias);
|
||||
|
||||
if (optionSchema == null)
|
||||
continue;
|
||||
|
||||
@@ -1,9 +1,16 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using CliFx.Models;
|
||||
|
||||
namespace CliFx.Services
|
||||
{
|
||||
public static class Extensions
|
||||
{
|
||||
public static IReadOnlyList<CommandSchema> GetCommandSchemas(this ICommandSchemaResolver resolver,
|
||||
IReadOnlyList<Type> commandTypes) =>
|
||||
commandTypes.Select(resolver.GetCommandSchema).ToArray();
|
||||
|
||||
public static void WithColor(this IConsole console, ConsoleColor foregroundColor, Action<IConsole> action)
|
||||
{
|
||||
var lastForegroundColor = console.ForegroundColor;
|
||||
|
||||
Reference in New Issue
Block a user