mirror of
https://github.com/Tyrrrz/CliFx.git
synced 2025-10-25 15:19:17 +00:00
Encapsulate application title, executable name, and version to ApplicationMetadata
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
@@ -12,6 +13,7 @@ namespace CliFx
|
||||
{
|
||||
public partial class CliApplication : ICliApplication
|
||||
{
|
||||
private readonly ApplicationMetadata _applicationMetadata;
|
||||
private readonly IReadOnlyList<Type> _commandTypes;
|
||||
private readonly ICommandInputParser _commandInputParser;
|
||||
private readonly ICommandSchemaResolver _commandSchemaResolver;
|
||||
@@ -19,10 +21,11 @@ namespace CliFx
|
||||
private readonly ICommandInitializer _commandInitializer;
|
||||
private readonly ICommandHelpTextBuilder _commandHelpTextBuilder;
|
||||
|
||||
public CliApplication(IReadOnlyList<Type> commandTypes,
|
||||
public CliApplication(ApplicationMetadata applicationMetadata, IReadOnlyList<Type> commandTypes,
|
||||
ICommandInputParser commandInputParser, ICommandSchemaResolver commandSchemaResolver,
|
||||
ICommandFactory commandFactory, ICommandInitializer commandInitializer, ICommandHelpTextBuilder commandHelpTextBuilder)
|
||||
{
|
||||
_applicationMetadata = applicationMetadata;
|
||||
_commandTypes = commandTypes;
|
||||
_commandInputParser = commandInputParser;
|
||||
_commandSchemaResolver = commandSchemaResolver;
|
||||
@@ -31,13 +34,18 @@ namespace CliFx
|
||||
_commandHelpTextBuilder = commandHelpTextBuilder;
|
||||
}
|
||||
|
||||
public CliApplication(IReadOnlyList<Type> commandTypes)
|
||||
: this(commandTypes,
|
||||
public CliApplication(ApplicationMetadata applicationMetadata, IReadOnlyList<Type> commandTypes)
|
||||
: this(applicationMetadata, commandTypes,
|
||||
new CommandInputParser(), new CommandSchemaResolver(), new CommandFactory(),
|
||||
new CommandInitializer(), new CommandHelpTextBuilder())
|
||||
{
|
||||
}
|
||||
|
||||
public CliApplication(IReadOnlyList<Type> commandTypes)
|
||||
: this(GetDefaultApplicationMetadata(), commandTypes)
|
||||
{
|
||||
}
|
||||
|
||||
public CliApplication()
|
||||
: this(GetDefaultCommandTypes())
|
||||
{
|
||||
@@ -78,15 +86,14 @@ namespace CliFx
|
||||
// Show version if it was requested without specifying a command
|
||||
if (commandInput.IsVersionRequested() && !commandInput.IsCommandSpecified())
|
||||
{
|
||||
var versionText = Assembly.GetEntryAssembly()?.GetName().Version.ToString();
|
||||
stdOut.WriteLine(versionText);
|
||||
stdOut.WriteLine(_applicationMetadata.VersionText);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Show help if it was requested
|
||||
if (commandInput.IsHelpRequested())
|
||||
{
|
||||
var helpText = _commandHelpTextBuilder.Build(availableCommandSchemas, matchingCommandSchema);
|
||||
var helpText = _commandHelpTextBuilder.Build(_applicationMetadata, availableCommandSchemas, matchingCommandSchema);
|
||||
stdOut.WriteLine(helpText);
|
||||
return 0;
|
||||
}
|
||||
@@ -100,7 +107,10 @@ namespace CliFx
|
||||
_commandInitializer.InitializeCommand(command, matchingCommandSchema, commandInput);
|
||||
|
||||
// Create context and execute command
|
||||
var commandContext = new CommandContext(commandInput, availableCommandSchemas, matchingCommandSchema, stdOut, stdErr);
|
||||
var commandContext = new CommandContext(_applicationMetadata,
|
||||
availableCommandSchemas, matchingCommandSchema,
|
||||
commandInput, stdOut, stdErr);
|
||||
|
||||
await command.ExecuteAsync(commandContext);
|
||||
|
||||
return 0;
|
||||
@@ -120,9 +130,28 @@ namespace CliFx
|
||||
|
||||
public partial class CliApplication
|
||||
{
|
||||
private static IReadOnlyList<Type> GetDefaultCommandTypes() =>
|
||||
Assembly.GetEntryAssembly()?.ExportedTypes.Where(t => t.Implements(typeof(ICommand))).ToArray() ??
|
||||
Type.EmptyTypes;
|
||||
private static ApplicationMetadata GetDefaultApplicationMetadata()
|
||||
{
|
||||
// Entry assembly is null in tests
|
||||
var entryAssembly = Assembly.GetEntryAssembly();
|
||||
|
||||
var title = entryAssembly?.GetName().FullName ?? "App";
|
||||
var executableName = Path.GetFileNameWithoutExtension(entryAssembly?.Location) ?? "app";
|
||||
var versionText = entryAssembly?.GetName().Version.ToString() ?? "1.0";
|
||||
|
||||
return new ApplicationMetadata(title, executableName, versionText);
|
||||
}
|
||||
|
||||
private static IReadOnlyList<Type> GetDefaultCommandTypes()
|
||||
{
|
||||
// Entry assembly is null in tests
|
||||
var entryAssembly = Assembly.GetEntryAssembly();
|
||||
|
||||
if (entryAssembly == null)
|
||||
return Type.EmptyTypes;
|
||||
|
||||
return entryAssembly.ExportedTypes.Where(t => t.Implements(typeof(ICommand))).ToArray();
|
||||
}
|
||||
|
||||
private sealed class StubDefaultCommand : ICommand
|
||||
{
|
||||
@@ -135,8 +164,12 @@ namespace CliFx
|
||||
|
||||
public Task ExecuteAsync(CommandContext context)
|
||||
{
|
||||
var helpText = _commandHelpTextBuilder.Build(context.AvailableCommandSchemas, context.MatchingCommandSchema);
|
||||
var helpText = _commandHelpTextBuilder.Build(context.ApplicationMetadata,
|
||||
context.AvailableCommandSchemas,
|
||||
context.MatchingCommandSchema);
|
||||
|
||||
context.Output.WriteLine(helpText);
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
|
||||
18
CliFx/Models/ApplicationMetadata.cs
Normal file
18
CliFx/Models/ApplicationMetadata.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
namespace CliFx.Models
|
||||
{
|
||||
public class ApplicationMetadata
|
||||
{
|
||||
public string Title { get; }
|
||||
|
||||
public string ExecutableName { get; }
|
||||
|
||||
public string VersionText { get; }
|
||||
|
||||
public ApplicationMetadata(string title, string executableName, string versionText)
|
||||
{
|
||||
Title = title;
|
||||
ExecutableName = executableName;
|
||||
VersionText = versionText;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,23 +5,26 @@ namespace CliFx.Models
|
||||
{
|
||||
public class CommandContext
|
||||
{
|
||||
public CommandInput CommandInput { get; }
|
||||
public ApplicationMetadata ApplicationMetadata { get; }
|
||||
|
||||
public IReadOnlyList<CommandSchema> AvailableCommandSchemas { get; }
|
||||
|
||||
public CommandSchema MatchingCommandSchema { get; }
|
||||
|
||||
public CommandInput CommandInput { get; }
|
||||
|
||||
public IConsoleWriter Output { get; }
|
||||
|
||||
public IConsoleWriter Error { get; }
|
||||
|
||||
public CommandContext(CommandInput commandInput,
|
||||
public CommandContext(ApplicationMetadata applicationMetadata,
|
||||
IReadOnlyList<CommandSchema> availableCommandSchemas, CommandSchema matchingCommandSchema,
|
||||
IConsoleWriter output, IConsoleWriter error)
|
||||
CommandInput commandInput, IConsoleWriter output, IConsoleWriter error)
|
||||
{
|
||||
CommandInput = commandInput;
|
||||
ApplicationMetadata = applicationMetadata;
|
||||
AvailableCommandSchemas = availableCommandSchemas;
|
||||
MatchingCommandSchema = matchingCommandSchema;
|
||||
CommandInput = commandInput;
|
||||
Output = output;
|
||||
Error = error;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using CliFx.Internal;
|
||||
using CliFx.Models;
|
||||
@@ -11,10 +9,6 @@ namespace CliFx.Services
|
||||
// TODO: add color
|
||||
public class CommandHelpTextBuilder : ICommandHelpTextBuilder
|
||||
{
|
||||
// TODO: move to context?
|
||||
// Entry assembly is null in tests
|
||||
private string GetExeName() => Path.GetFileNameWithoutExtension(Assembly.GetEntryAssembly()?.Location) ?? "app";
|
||||
|
||||
private void AddDescription(StringBuilder buffer, CommandSchema commands)
|
||||
{
|
||||
if (commands.Description.IsNullOrWhiteSpace())
|
||||
@@ -28,12 +22,13 @@ namespace CliFx.Services
|
||||
buffer.AppendLine();
|
||||
}
|
||||
|
||||
private void AddUsage(StringBuilder buffer, CommandSchema command, IReadOnlyList<CommandSchema> subCommands)
|
||||
private void AddUsage(StringBuilder buffer, ApplicationMetadata applicationMetadata, CommandSchema command,
|
||||
IReadOnlyList<CommandSchema> subCommands)
|
||||
{
|
||||
buffer.AppendLine("Usage:");
|
||||
|
||||
buffer.Append(" ");
|
||||
buffer.Append(GetExeName());
|
||||
buffer.Append(applicationMetadata.ExecutableName);
|
||||
|
||||
if (!command.Name.IsNullOrWhiteSpace())
|
||||
{
|
||||
@@ -119,21 +114,31 @@ namespace CliFx.Services
|
||||
buffer.AppendLine();
|
||||
}
|
||||
|
||||
public string Build(IReadOnlyList<CommandSchema> availableCommandSchemas, CommandSchema matchingCommandSchema)
|
||||
public string Build(ApplicationMetadata applicationMetadata,
|
||||
IReadOnlyList<CommandSchema> availableCommandSchemas,
|
||||
CommandSchema matchingCommandSchema)
|
||||
{
|
||||
var buffer = new StringBuilder();
|
||||
|
||||
var subCommands = availableCommandSchemas.FindSubCommandSchemas(matchingCommandSchema.Name);
|
||||
|
||||
var buffer = new StringBuilder();
|
||||
|
||||
if (matchingCommandSchema.IsDefault())
|
||||
{
|
||||
buffer.Append(applicationMetadata.Title);
|
||||
buffer.Append(" v");
|
||||
buffer.Append(applicationMetadata.VersionText);
|
||||
buffer.AppendLine().AppendLine();
|
||||
}
|
||||
|
||||
AddDescription(buffer, matchingCommandSchema);
|
||||
AddUsage(buffer, matchingCommandSchema, subCommands);
|
||||
AddUsage(buffer, applicationMetadata, matchingCommandSchema, subCommands);
|
||||
AddOptions(buffer, matchingCommandSchema);
|
||||
AddSubCommands(buffer, subCommands);
|
||||
|
||||
if (matchingCommandSchema.IsDefault() && subCommands.Any())
|
||||
{
|
||||
buffer.Append("You can run ");
|
||||
buffer.Append('`').Append(GetExeName()).Append(" [command] --help").Append('`');
|
||||
buffer.Append('`').Append(applicationMetadata.ExecutableName).Append(" [command] --help").Append('`');
|
||||
buffer.Append(" to show help on a specific command.");
|
||||
buffer.AppendLine();
|
||||
}
|
||||
|
||||
@@ -5,6 +5,8 @@ namespace CliFx.Services
|
||||
{
|
||||
public interface ICommandHelpTextBuilder
|
||||
{
|
||||
string Build(IReadOnlyList<CommandSchema> availableCommandSchemas, CommandSchema matchingCommandSchema);
|
||||
string Build(ApplicationMetadata applicationMetadata,
|
||||
IReadOnlyList<CommandSchema> availableCommandSchemas,
|
||||
CommandSchema matchingCommandSchema);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user