mirror of
https://github.com/Tyrrrz/CliFx.git
synced 2025-10-25 15:19:17 +00:00
Add xml documentation
This commit is contained in:
@@ -1,20 +1,34 @@
|
||||
using System;
|
||||
using CliFx.Internal;
|
||||
|
||||
namespace CliFx.Attributes
|
||||
{
|
||||
/// <summary>
|
||||
/// Annotates a type that defines a command.
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Class, Inherited = false)]
|
||||
public class CommandAttribute : Attribute
|
||||
{
|
||||
/// <summary>
|
||||
/// Command name.
|
||||
/// </summary>
|
||||
public string Name { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Command description, which is used in help text.
|
||||
/// </summary>
|
||||
public string Description { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes an instance of <see cref="CommandAttribute"/>.
|
||||
/// </summary>
|
||||
public CommandAttribute(string name)
|
||||
{
|
||||
Name = name;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes an instance of <see cref="CommandAttribute"/>.
|
||||
/// </summary>
|
||||
public CommandAttribute()
|
||||
: this(null)
|
||||
{
|
||||
|
||||
@@ -2,35 +2,65 @@
|
||||
|
||||
namespace CliFx.Attributes
|
||||
{
|
||||
/// <summary>
|
||||
/// Annotates a property that defines a command option.
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Property)]
|
||||
public class CommandOptionAttribute : Attribute
|
||||
{
|
||||
/// <summary>
|
||||
/// Option name.
|
||||
/// </summary>
|
||||
public string Name { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Option short name.
|
||||
/// </summary>
|
||||
public char? ShortName { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Option group name.
|
||||
/// </summary>
|
||||
public string GroupName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether an option is required.
|
||||
/// </summary>
|
||||
public bool IsRequired { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Option description, which is used in help text.
|
||||
/// </summary>
|
||||
public string Description { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes an instance of <see cref="CommandOptionAttribute"/>.
|
||||
/// </summary>
|
||||
public CommandOptionAttribute(string name, char? shortName)
|
||||
{
|
||||
Name = name;
|
||||
ShortName = shortName;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes an instance of <see cref="CommandOptionAttribute"/>.
|
||||
/// </summary>
|
||||
public CommandOptionAttribute(string name, char shortName)
|
||||
: this(name, (char?) shortName)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes an instance of <see cref="CommandOptionAttribute"/>.
|
||||
/// </summary>
|
||||
public CommandOptionAttribute(string name)
|
||||
: this(name, null)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes an instance of <see cref="CommandOptionAttribute"/>.
|
||||
/// </summary>
|
||||
public CommandOptionAttribute(char shortName)
|
||||
: this(null, shortName)
|
||||
{
|
||||
|
||||
@@ -10,6 +10,9 @@ using CliFx.Services;
|
||||
|
||||
namespace CliFx
|
||||
{
|
||||
/// <summary>
|
||||
/// Default implementation of <see cref="ICliApplication"/>.
|
||||
/// </summary>
|
||||
public partial class CliApplication : ICliApplication
|
||||
{
|
||||
private readonly ApplicationMetadata _applicationMetadata;
|
||||
@@ -22,6 +25,9 @@ namespace CliFx
|
||||
private readonly ICommandInitializer _commandInitializer;
|
||||
private readonly ICommandHelpTextRenderer _commandHelpTextRenderer;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes an instance of <see cref="CliApplication"/>.
|
||||
/// </summary>
|
||||
public CliApplication(ApplicationMetadata applicationMetadata, IReadOnlyList<Type> commandTypes,
|
||||
IConsole console, ICommandInputParser commandInputParser, ICommandSchemaResolver commandSchemaResolver,
|
||||
ICommandFactory commandFactory, ICommandInitializer commandInitializer, ICommandHelpTextRenderer commandHelpTextRenderer)
|
||||
@@ -98,6 +104,7 @@ namespace CliFx
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<int> RunAsync(IReadOnlyList<string> commandLineArguments)
|
||||
{
|
||||
try
|
||||
|
||||
@@ -9,6 +9,9 @@ using CliFx.Services;
|
||||
|
||||
namespace CliFx
|
||||
{
|
||||
/// <summary>
|
||||
/// Default implementation of <see cref="ICliApplicationBuilder"/>.
|
||||
/// </summary>
|
||||
public class CliApplicationBuilder : ICliApplicationBuilder
|
||||
{
|
||||
private readonly HashSet<Type> _commandTypes = new HashSet<Type>();
|
||||
@@ -19,12 +22,14 @@ namespace CliFx
|
||||
private IConsole _console;
|
||||
private ICommandFactory _commandFactory;
|
||||
|
||||
/// <inheritdoc />
|
||||
public ICliApplicationBuilder WithCommand(Type commandType)
|
||||
{
|
||||
_commandTypes.Add(commandType);
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public ICliApplicationBuilder WithCommandsFrom(Assembly commandAssembly)
|
||||
{
|
||||
var commandTypes = commandAssembly.ExportedTypes.Where(t => t.Implements(typeof(ICommand)));
|
||||
@@ -35,30 +40,35 @@ namespace CliFx
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public ICliApplicationBuilder UseTitle(string title)
|
||||
{
|
||||
_title = title;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ICliApplicationBuilder UseExecutableName(string exeName)
|
||||
/// <inheritdoc />
|
||||
public ICliApplicationBuilder UseExecutableName(string executableName)
|
||||
{
|
||||
_executableName = exeName;
|
||||
_executableName = executableName;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public ICliApplicationBuilder UseVersionText(string version)
|
||||
{
|
||||
_versionText = version;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public ICliApplicationBuilder UseConsole(IConsole console)
|
||||
{
|
||||
_console = console;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public ICliApplicationBuilder UseCommandFactory(ICommandFactory factory)
|
||||
{
|
||||
_commandFactory = factory;
|
||||
@@ -86,6 +96,7 @@ namespace CliFx
|
||||
UseCommandFactory(new CommandFactory());
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public ICliApplication Build()
|
||||
{
|
||||
// Use defaults for required parameters that were not configured
|
||||
|
||||
@@ -2,17 +2,29 @@
|
||||
|
||||
namespace CliFx.Exceptions
|
||||
{
|
||||
/// <summary>
|
||||
/// Thrown when an input command option can't be converted.
|
||||
/// </summary>
|
||||
public class CannotConvertCommandOptionException : CliFxException
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes an instance of <see cref="CannotConvertCommandOptionException"/>.
|
||||
/// </summary>
|
||||
public CannotConvertCommandOptionException()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes an instance of <see cref="CannotConvertCommandOptionException"/>.
|
||||
/// </summary>
|
||||
public CannotConvertCommandOptionException(string message)
|
||||
: base(message)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes an instance of <see cref="CannotConvertCommandOptionException"/>.
|
||||
/// </summary>
|
||||
public CannotConvertCommandOptionException(string message, Exception innerException)
|
||||
: base(message, innerException)
|
||||
{
|
||||
|
||||
@@ -2,18 +2,30 @@
|
||||
|
||||
namespace CliFx.Exceptions
|
||||
{
|
||||
/// <summary>
|
||||
/// Domain exception thrown within CliFx.
|
||||
/// </summary>
|
||||
public abstract class CliFxException : Exception
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes an instance of <see cref="CliFxException"/>.
|
||||
/// </summary>
|
||||
protected CliFxException(string message)
|
||||
: base(message)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes an instance of <see cref="CliFxException"/>.
|
||||
/// </summary>
|
||||
protected CliFxException(string message, Exception innerException)
|
||||
: base(message, innerException)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes an instance of <see cref="CliFxException"/>.
|
||||
/// </summary>
|
||||
protected CliFxException()
|
||||
{
|
||||
}
|
||||
|
||||
@@ -2,26 +2,45 @@
|
||||
|
||||
namespace CliFx.Exceptions
|
||||
{
|
||||
/// <summary>
|
||||
/// Thrown when a command cannot proceed with normal execution due to error.
|
||||
/// Use this exception if you want to specify an exit code to use when the process terminates.
|
||||
/// </summary>
|
||||
public class CommandErrorException : CliFxException
|
||||
{
|
||||
/// <summary>
|
||||
/// Process exit code.
|
||||
/// </summary>
|
||||
public int ExitCode { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes an instance of <see cref="CommandErrorException"/>.
|
||||
/// </summary>
|
||||
public CommandErrorException(int exitCode, string message, Exception innerException)
|
||||
: base(message, innerException)
|
||||
{
|
||||
ExitCode = exitCode;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes an instance of <see cref="CommandErrorException"/>.
|
||||
/// </summary>
|
||||
public CommandErrorException(int exitCode, Exception innerException)
|
||||
: this(exitCode, null, innerException)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes an instance of <see cref="CommandErrorException"/>.
|
||||
/// </summary>
|
||||
public CommandErrorException(int exitCode, string message)
|
||||
: this(exitCode, message, null)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes an instance of <see cref="CommandErrorException"/>.
|
||||
/// </summary>
|
||||
public CommandErrorException(int exitCode)
|
||||
: this(exitCode, null, null)
|
||||
{
|
||||
|
||||
@@ -2,17 +2,29 @@
|
||||
|
||||
namespace CliFx.Exceptions
|
||||
{
|
||||
/// <summary>
|
||||
/// Thrown when a required command option was not set.
|
||||
/// </summary>
|
||||
public class MissingCommandOptionException : CliFxException
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes an instance of <see cref="MissingCommandOptionException"/>.
|
||||
/// </summary>
|
||||
public MissingCommandOptionException()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes an instance of <see cref="MissingCommandOptionException"/>.
|
||||
/// </summary>
|
||||
public MissingCommandOptionException(string message)
|
||||
: base(message)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes an instance of <see cref="MissingCommandOptionException"/>.
|
||||
/// </summary>
|
||||
public MissingCommandOptionException(string message, Exception innerException)
|
||||
: base(message, innerException)
|
||||
{
|
||||
|
||||
@@ -5,8 +5,14 @@ using CliFx.Services;
|
||||
|
||||
namespace CliFx
|
||||
{
|
||||
/// <summary>
|
||||
/// Extensions for <see cref="CliFx"/>.
|
||||
/// </summary>
|
||||
public static class Extensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Adds multiple commands to the application.
|
||||
/// </summary>
|
||||
public static ICliApplicationBuilder WithCommands(this ICliApplicationBuilder builder, IReadOnlyList<Type> commandTypes)
|
||||
{
|
||||
foreach (var commandType in commandTypes)
|
||||
@@ -15,6 +21,9 @@ namespace CliFx
|
||||
return builder;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds commands from specified assemblies to the application.
|
||||
/// </summary>
|
||||
public static ICliApplicationBuilder WithCommandsFrom(this ICliApplicationBuilder builder, IReadOnlyList<Assembly> commandAssemblies)
|
||||
{
|
||||
foreach (var commandAssembly in commandAssemblies)
|
||||
@@ -23,9 +32,15 @@ namespace CliFx
|
||||
return builder;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds commands from calling assembly to the application.
|
||||
/// </summary>
|
||||
public static ICliApplicationBuilder WithCommandsFromThisAssembly(this ICliApplicationBuilder builder) =>
|
||||
builder.WithCommandsFrom(Assembly.GetCallingAssembly());
|
||||
|
||||
/// <summary>
|
||||
/// Configures application to use specified factory method for creating new instances of <see cref="ICommand"/>.
|
||||
/// </summary>
|
||||
public static ICliApplicationBuilder UseCommandFactory(this ICliApplicationBuilder builder, Func<Type, ICommand> factoryMethod) =>
|
||||
builder.UseCommandFactory(new DelegateCommandFactory(factoryMethod));
|
||||
}
|
||||
|
||||
@@ -3,8 +3,15 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace CliFx
|
||||
{
|
||||
/// <summary>
|
||||
/// Entry point for a command line application.
|
||||
/// </summary>
|
||||
public interface ICliApplication
|
||||
{
|
||||
/// <summary>
|
||||
/// Runs application with specified command line arguments.
|
||||
/// Returns exit code.
|
||||
/// </summary>
|
||||
Task<int> RunAsync(IReadOnlyList<string> commandLineArguments);
|
||||
}
|
||||
}
|
||||
@@ -4,22 +4,50 @@ using CliFx.Services;
|
||||
|
||||
namespace CliFx
|
||||
{
|
||||
/// <summary>
|
||||
/// Builds an instance of <see cref="ICliApplication"/>.
|
||||
/// </summary>
|
||||
public interface ICliApplicationBuilder
|
||||
{
|
||||
/// <summary>
|
||||
/// Adds a command of specified type to the application.
|
||||
/// </summary>
|
||||
ICliApplicationBuilder WithCommand(Type commandType);
|
||||
|
||||
/// <summary>
|
||||
/// Adds commands from specified assembly to the application.
|
||||
/// </summary>
|
||||
ICliApplicationBuilder WithCommandsFrom(Assembly commandAssembly);
|
||||
|
||||
/// <summary>
|
||||
/// Sets application title, which appears in the help text.
|
||||
/// </summary>
|
||||
ICliApplicationBuilder UseTitle(string title);
|
||||
|
||||
ICliApplicationBuilder UseExecutableName(string exeName);
|
||||
/// <summary>
|
||||
/// Sets application executable name, which appears in the help text.
|
||||
/// </summary>
|
||||
ICliApplicationBuilder UseExecutableName(string executableName);
|
||||
|
||||
/// <summary>
|
||||
/// Sets application version text, which appears in the help text and when the user requests version information.
|
||||
/// </summary>
|
||||
ICliApplicationBuilder UseVersionText(string version);
|
||||
|
||||
/// <summary>
|
||||
/// Configures application to use specified implementation of <see cref="IConsole"/>.
|
||||
/// </summary>
|
||||
ICliApplicationBuilder UseConsole(IConsole console);
|
||||
|
||||
/// <summary>
|
||||
/// Configures application to use specified implementation of <see cref="ICommandFactory"/>.
|
||||
/// </summary>
|
||||
ICliApplicationBuilder UseCommandFactory(ICommandFactory factory);
|
||||
|
||||
/// <summary>
|
||||
/// Creates an instance of <see cref="ICliApplication"/> using configured parameters.
|
||||
/// Default values are used in place of parameters that were not specified.
|
||||
/// </summary>
|
||||
ICliApplication Build();
|
||||
}
|
||||
}
|
||||
@@ -3,8 +3,15 @@ using CliFx.Services;
|
||||
|
||||
namespace CliFx
|
||||
{
|
||||
/// <summary>
|
||||
/// Point of interaction between a user and command line interface.
|
||||
/// </summary>
|
||||
public interface ICommand
|
||||
{
|
||||
/// <summary>
|
||||
/// Executes command using specified implementation of <see cref="IConsole"/>.
|
||||
/// This method is called when the command is invoked by a user through command line interface.
|
||||
/// </summary>
|
||||
Task ExecuteAsync(IConsole console);
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,28 @@
|
||||
namespace CliFx.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// Metadata associated with an application.
|
||||
/// </summary>
|
||||
public class ApplicationMetadata
|
||||
{
|
||||
/// <summary>
|
||||
/// Application title.
|
||||
/// </summary>
|
||||
public string Title { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Application executable name.
|
||||
/// </summary>
|
||||
public string ExecutableName { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Application version text.
|
||||
/// </summary>
|
||||
public string VersionText { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes an instance of <see cref="ApplicationMetadata"/>.
|
||||
/// </summary>
|
||||
public ApplicationMetadata(string title, string executableName, string versionText)
|
||||
{
|
||||
Title = title;
|
||||
|
||||
@@ -4,33 +4,55 @@ using CliFx.Internal;
|
||||
|
||||
namespace CliFx.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// Parsed command line input.
|
||||
/// </summary>
|
||||
public partial class CommandInput
|
||||
{
|
||||
/// <summary>
|
||||
/// Specified command name.
|
||||
/// </summary>
|
||||
public string CommandName { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Specified options.
|
||||
/// </summary>
|
||||
public IReadOnlyList<CommandOptionInput> Options { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes an instance of <see cref="CommandInput"/>.
|
||||
/// </summary>
|
||||
public CommandInput(string commandName, IReadOnlyList<CommandOptionInput> options)
|
||||
{
|
||||
CommandName = commandName;
|
||||
Options = options;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes an instance of <see cref="CommandInput"/>.
|
||||
/// </summary>
|
||||
public CommandInput(IReadOnlyList<CommandOptionInput> options)
|
||||
: this(null, options)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes an instance of <see cref="CommandInput"/>.
|
||||
/// </summary>
|
||||
public CommandInput(string commandName)
|
||||
: this(commandName, new CommandOptionInput[0])
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes an instance of <see cref="CommandInput"/>.
|
||||
/// </summary>
|
||||
public CommandInput()
|
||||
: this(null, new CommandOptionInput[0])
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string ToString()
|
||||
{
|
||||
var buffer = new StringBuilder();
|
||||
@@ -53,6 +75,9 @@ namespace CliFx.Models
|
||||
|
||||
public partial class CommandInput
|
||||
{
|
||||
/// <summary>
|
||||
/// Empty input.
|
||||
/// </summary>
|
||||
public static CommandInput Empty { get; } = new CommandInput();
|
||||
}
|
||||
}
|
||||
@@ -3,28 +3,47 @@ using System.Text;
|
||||
|
||||
namespace CliFx.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// Parsed option from command line input.
|
||||
/// </summary>
|
||||
public class CommandOptionInput
|
||||
{
|
||||
/// <summary>
|
||||
/// Specified option alias.
|
||||
/// </summary>
|
||||
public string Alias { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Specified values.
|
||||
/// </summary>
|
||||
public IReadOnlyList<string> Values { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes an instance of <see cref="CommandOptionInput"/>.
|
||||
/// </summary>
|
||||
public CommandOptionInput(string alias, IReadOnlyList<string> values)
|
||||
{
|
||||
Alias = alias;
|
||||
Values = values;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes an instance of <see cref="CommandOptionInput"/>.
|
||||
/// </summary>
|
||||
public CommandOptionInput(string alias, string value)
|
||||
: this(alias, new[] {value})
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes an instance of <see cref="CommandOptionInput"/>.
|
||||
/// </summary>
|
||||
public CommandOptionInput(string alias)
|
||||
: this(alias, new string[0])
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string ToString()
|
||||
{
|
||||
var buffer = new StringBuilder();
|
||||
|
||||
@@ -4,20 +4,44 @@ using CliFx.Internal;
|
||||
|
||||
namespace CliFx.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// Schema of a defined command option.
|
||||
/// </summary>
|
||||
public class CommandOptionSchema
|
||||
{
|
||||
/// <summary>
|
||||
/// Underlying property.
|
||||
/// </summary>
|
||||
public PropertyInfo Property { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Option name.
|
||||
/// </summary>
|
||||
public string Name { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Option short name.
|
||||
/// </summary>
|
||||
public char? ShortName { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Option group name.
|
||||
/// </summary>
|
||||
public string GroupName { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether an option is required.
|
||||
/// </summary>
|
||||
public bool IsRequired { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Option description.
|
||||
/// </summary>
|
||||
public string Description { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes an instance of <see cref="CommandOptionSchema"/>.
|
||||
/// </summary>
|
||||
public CommandOptionSchema(PropertyInfo property, string name, char? shortName,
|
||||
string groupName, bool isRequired, string description)
|
||||
{
|
||||
@@ -29,6 +53,7 @@ namespace CliFx.Models
|
||||
Description = description;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string ToString()
|
||||
{
|
||||
var buffer = new StringBuilder();
|
||||
|
||||
@@ -5,16 +5,34 @@ using CliFx.Internal;
|
||||
|
||||
namespace CliFx.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// Schema of a defined command.
|
||||
/// </summary>
|
||||
public class CommandSchema
|
||||
{
|
||||
/// <summary>
|
||||
/// Underlying type.
|
||||
/// </summary>
|
||||
public Type Type { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Command name.
|
||||
/// </summary>
|
||||
public string Name { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Command description.
|
||||
/// </summary>
|
||||
public string Description { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Command options.
|
||||
/// </summary>
|
||||
public IReadOnlyList<CommandOptionSchema> Options { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes an instance of <see cref="CommandSchema"/>.
|
||||
/// </summary>
|
||||
public CommandSchema(Type type, string name, string description, IReadOnlyList<CommandOptionSchema> options)
|
||||
{
|
||||
Type = type;
|
||||
@@ -23,6 +41,7 @@ namespace CliFx.Models
|
||||
Options = options;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string ToString()
|
||||
{
|
||||
var buffer = new StringBuilder();
|
||||
|
||||
@@ -5,10 +5,19 @@ using CliFx.Internal;
|
||||
|
||||
namespace CliFx.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// Extensions for <see cref="Models"/>.
|
||||
/// </summary>
|
||||
public static class Extensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets whether a command was specified in the input.
|
||||
/// </summary>
|
||||
public static bool IsCommandSpecified(this CommandInput commandInput) => !commandInput.CommandName.IsNullOrWhiteSpace();
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether help was requested in the input.
|
||||
/// </summary>
|
||||
public static bool IsHelpRequested(this CommandInput commandInput)
|
||||
{
|
||||
var firstOptionAlias = commandInput.Options.FirstOrDefault()?.Alias;
|
||||
@@ -18,6 +27,9 @@ namespace CliFx.Models
|
||||
string.Equals(firstOptionAlias, "?", StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether version information was requested in the input.
|
||||
/// </summary>
|
||||
public static bool IsVersionRequested(this CommandInput commandInput)
|
||||
{
|
||||
var firstOptionAlias = commandInput.Options.FirstOrDefault()?.Alias;
|
||||
@@ -25,11 +37,20 @@ namespace CliFx.Models
|
||||
return string.Equals(firstOptionAlias, "version", StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether this command is the default command, i.e. without a name.
|
||||
/// </summary>
|
||||
public static bool IsDefault(this CommandSchema commandSchema) => commandSchema.Name.IsNullOrWhiteSpace();
|
||||
|
||||
/// <summary>
|
||||
/// Finds a command that has specified name, or null if not found.
|
||||
/// </summary>
|
||||
public static CommandSchema FindByName(this IReadOnlyList<CommandSchema> commandSchemas, string commandName) =>
|
||||
commandSchemas.FirstOrDefault(c => string.Equals(c.Name, commandName, StringComparison.OrdinalIgnoreCase));
|
||||
|
||||
/// <summary>
|
||||
/// Finds parent command to the command that has specified name, or null if not found.
|
||||
/// </summary>
|
||||
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
|
||||
@@ -51,6 +72,9 @@ namespace CliFx.Models
|
||||
return commandSchemas.FirstOrDefault(c => c.IsDefault());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finds an option that matches specified alias, or null if not found.
|
||||
/// </summary>
|
||||
public static CommandOptionSchema FindByAlias(this IReadOnlyList<CommandOptionSchema> optionSchemas, string alias)
|
||||
{
|
||||
foreach (var optionSchema in optionSchemas)
|
||||
|
||||
@@ -2,14 +2,29 @@
|
||||
|
||||
namespace CliFx.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// Source information used to generate help text.
|
||||
/// </summary>
|
||||
public class HelpTextSource
|
||||
{
|
||||
/// <summary>
|
||||
/// Application metadata.
|
||||
/// </summary>
|
||||
public ApplicationMetadata ApplicationMetadata { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Schemas of commands available in the application.
|
||||
/// </summary>
|
||||
public IReadOnlyList<CommandSchema> AvailableCommandSchemas { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Schema of the command for which help text is to be generated.
|
||||
/// </summary>
|
||||
public CommandSchema TargetCommandSchema { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes an instance of <see cref="HelpTextSource"/>.
|
||||
/// </summary>
|
||||
public HelpTextSource(ApplicationMetadata applicationMetadata,
|
||||
IReadOnlyList<CommandSchema> availableCommandSchemas,
|
||||
CommandSchema targetCommandSchema)
|
||||
|
||||
@@ -2,8 +2,12 @@
|
||||
|
||||
namespace CliFx.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Default implementation of <see cref="ICommandFactory"/>.
|
||||
/// </summary>
|
||||
public class CommandFactory : ICommandFactory
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public ICommand CreateCommand(Type commandType) => (ICommand) Activator.CreateInstance(commandType);
|
||||
}
|
||||
}
|
||||
@@ -6,8 +6,12 @@ using CliFx.Models;
|
||||
|
||||
namespace CliFx.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Default implementation of <see cref="ICommandHelpTextRenderer"/>.
|
||||
/// </summary>
|
||||
public partial class CommandHelpTextRenderer : ICommandHelpTextRenderer
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public void RenderHelpText(IConsole console, HelpTextSource source) => new Impl(console, source).RenderHelpText();
|
||||
}
|
||||
|
||||
|
||||
@@ -7,20 +7,30 @@ using CliFx.Models;
|
||||
|
||||
namespace CliFx.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Default implementation of <see cref="ICommandInitializer"/>.
|
||||
/// </summary>
|
||||
public class CommandInitializer : ICommandInitializer
|
||||
{
|
||||
private readonly ICommandOptionInputConverter _commandOptionInputConverter;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes an instance of <see cref="CommandInitializer"/>.
|
||||
/// </summary>
|
||||
public CommandInitializer(ICommandOptionInputConverter commandOptionInputConverter)
|
||||
{
|
||||
_commandOptionInputConverter = commandOptionInputConverter;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes an instance of <see cref="CommandInitializer"/>.
|
||||
/// </summary>
|
||||
public CommandInitializer()
|
||||
: this(new CommandOptionInputConverter())
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void InitializeCommand(ICommand command, CommandSchema schema, CommandInput input)
|
||||
{
|
||||
// Set command options
|
||||
|
||||
@@ -6,9 +6,13 @@ using CliFx.Models;
|
||||
|
||||
namespace CliFx.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Default implementation of <see cref="ICommandInputParser"/>.
|
||||
/// </summary>
|
||||
public class CommandInputParser : ICommandInputParser
|
||||
{
|
||||
// TODO: refactor
|
||||
/// <inheritdoc />
|
||||
public CommandInput ParseInput(IReadOnlyList<string> commandLineArguments)
|
||||
{
|
||||
// Initialize command name placeholder
|
||||
|
||||
@@ -8,15 +8,24 @@ using CliFx.Models;
|
||||
|
||||
namespace CliFx.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Default implementation of <see cref="ICommandOptionInputConverter"/>.
|
||||
/// </summary>
|
||||
public class CommandOptionInputConverter : ICommandOptionInputConverter
|
||||
{
|
||||
private readonly IFormatProvider _formatProvider;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes an instance of <see cref="CommandOptionInputConverter"/>.
|
||||
/// </summary>
|
||||
public CommandOptionInputConverter(IFormatProvider formatProvider)
|
||||
{
|
||||
_formatProvider = formatProvider;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes an instance of <see cref="CommandOptionInputConverter"/>.
|
||||
/// </summary>
|
||||
public CommandOptionInputConverter()
|
||||
: this(CultureInfo.InvariantCulture)
|
||||
{
|
||||
@@ -232,6 +241,7 @@ namespace CliFx.Services
|
||||
}
|
||||
|
||||
// TODO: refactor this
|
||||
/// <inheritdoc />
|
||||
public object ConvertOption(CommandOptionInput option, Type targetType)
|
||||
{
|
||||
if (targetType != typeof(string) && targetType.IsEnumerable())
|
||||
|
||||
@@ -7,6 +7,9 @@ using CliFx.Models;
|
||||
|
||||
namespace CliFx.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Default implementation of <see cref="ICommandSchemaResolver"/>.
|
||||
/// </summary>
|
||||
public class CommandSchemaResolver : ICommandSchemaResolver
|
||||
{
|
||||
private CommandOptionSchema GetCommandOptionSchema(PropertyInfo optionProperty)
|
||||
@@ -24,7 +27,7 @@ namespace CliFx.Services
|
||||
attribute.Description);
|
||||
}
|
||||
|
||||
// TODO: validate stuff like duplicate names, multiple default commands, etc
|
||||
/// <inheritdoc />
|
||||
public CommandSchema GetCommandSchema(Type commandType)
|
||||
{
|
||||
if (!commandType.Implements(typeof(ICommand)))
|
||||
|
||||
@@ -2,15 +2,22 @@
|
||||
|
||||
namespace CliFx.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Implementation of <see cref="ICommandFactory"/> that uses a factory method to create commands.
|
||||
/// </summary>
|
||||
public class DelegateCommandFactory : ICommandFactory
|
||||
{
|
||||
private readonly Func<Type, ICommand> _factoryMethod;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes an instance of <see cref="DelegateCommandFactory"/>.
|
||||
/// </summary>
|
||||
public DelegateCommandFactory(Func<Type, ICommand> factoryMethod)
|
||||
{
|
||||
_factoryMethod = factoryMethod;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public ICommand CreateCommand(Type commandType) => _factoryMethod(commandType);
|
||||
}
|
||||
}
|
||||
@@ -5,12 +5,20 @@ using CliFx.Models;
|
||||
|
||||
namespace CliFx.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Extensions for <see cref="Services"/>
|
||||
/// </summary>
|
||||
public static class Extensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Resolves command schemas for commands of specified types.
|
||||
/// </summary>
|
||||
public static IReadOnlyList<CommandSchema> GetCommandSchemas(this ICommandSchemaResolver resolver,
|
||||
IReadOnlyList<Type> commandTypes) =>
|
||||
commandTypes.Select(resolver.GetCommandSchema).ToArray();
|
||||
IReadOnlyList<Type> commandTypes) => commandTypes.Select(resolver.GetCommandSchema).ToArray();
|
||||
|
||||
/// <summary>
|
||||
/// Sets console foreground color, executes specified action, and sets the color back to the original value.
|
||||
/// </summary>
|
||||
public static void WithForegroundColor(this IConsole console, ConsoleColor foregroundColor, Action action)
|
||||
{
|
||||
var lastColor = console.ForegroundColor;
|
||||
@@ -21,6 +29,9 @@ namespace CliFx.Services
|
||||
console.ForegroundColor = lastColor;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets console background color, executes specified action, and sets the color back to the original value.
|
||||
/// </summary>
|
||||
public static void WithBackgroundColor(this IConsole console, ConsoleColor backgroundColor, Action action)
|
||||
{
|
||||
var lastColor = console.BackgroundColor;
|
||||
@@ -31,6 +42,9 @@ namespace CliFx.Services
|
||||
console.BackgroundColor = lastColor;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets console foreground and background colors, executes specified action, and sets the colors back to the original values.
|
||||
/// </summary>
|
||||
public static void WithColors(this IConsole console, ConsoleColor foregroundColor, ConsoleColor backgroundColor, Action action) =>
|
||||
console.WithForegroundColor(foregroundColor, () => console.WithBackgroundColor(backgroundColor, action));
|
||||
}
|
||||
|
||||
@@ -2,8 +2,14 @@
|
||||
|
||||
namespace CliFx.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes new instances of <see cref="ICommand"/>.
|
||||
/// </summary>
|
||||
public interface ICommandFactory
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes an instance of <see cref="ICommand"/> of specified type.
|
||||
/// </summary>
|
||||
ICommand CreateCommand(Type commandType);
|
||||
}
|
||||
}
|
||||
@@ -2,8 +2,14 @@
|
||||
|
||||
namespace CliFx.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Renders help text to the console.
|
||||
/// </summary>
|
||||
public interface ICommandHelpTextRenderer
|
||||
{
|
||||
/// <summary>
|
||||
/// Renders help text using specified console and source information.
|
||||
/// </summary>
|
||||
void RenderHelpText(IConsole console, HelpTextSource source);
|
||||
}
|
||||
}
|
||||
@@ -2,8 +2,14 @@
|
||||
|
||||
namespace CliFx.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Populates <see cref="ICommand"/> instances with input according to its schema.
|
||||
/// </summary>
|
||||
public interface ICommandInitializer
|
||||
{
|
||||
/// <summary>
|
||||
/// Populates an instance of <see cref="ICommand"/> with specified input according to specified schema.
|
||||
/// </summary>
|
||||
void InitializeCommand(ICommand command, CommandSchema schema, CommandInput input);
|
||||
}
|
||||
}
|
||||
@@ -3,8 +3,14 @@ using CliFx.Models;
|
||||
|
||||
namespace CliFx.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Parses command line arguments.
|
||||
/// </summary>
|
||||
public interface ICommandInputParser
|
||||
{
|
||||
/// <summary>
|
||||
/// Parses specified command line arguments.
|
||||
/// </summary>
|
||||
CommandInput ParseInput(IReadOnlyList<string> commandLineArguments);
|
||||
}
|
||||
}
|
||||
@@ -3,8 +3,14 @@ using CliFx.Models;
|
||||
|
||||
namespace CliFx.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Converts input command options.
|
||||
/// </summary>
|
||||
public interface ICommandOptionInputConverter
|
||||
{
|
||||
/// <summary>
|
||||
/// Converts an option to specified target type.
|
||||
/// </summary>
|
||||
object ConvertOption(CommandOptionInput option, Type targetType);
|
||||
}
|
||||
}
|
||||
@@ -3,8 +3,14 @@ using CliFx.Models;
|
||||
|
||||
namespace CliFx.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Resolves command schemas.
|
||||
/// </summary>
|
||||
public interface ICommandSchemaResolver
|
||||
{
|
||||
/// <summary>
|
||||
/// Resolves schema of a command of specified type.
|
||||
/// </summary>
|
||||
CommandSchema GetCommandSchema(Type commandType);
|
||||
}
|
||||
}
|
||||
@@ -3,24 +3,54 @@ using System.IO;
|
||||
|
||||
namespace CliFx.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Abstraction for interacting with the console.
|
||||
/// </summary>
|
||||
public interface IConsole
|
||||
{
|
||||
/// <summary>
|
||||
/// Input stream (stdin).
|
||||
/// </summary>
|
||||
TextReader Input { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether the input stream is redirected.
|
||||
/// </summary>
|
||||
bool IsInputRedirected { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Output stream (stdout).
|
||||
/// </summary>
|
||||
TextWriter Output { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether the output stream is redirected.
|
||||
/// </summary>
|
||||
bool IsOutputRedirected { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Error stream (stderr).
|
||||
/// </summary>
|
||||
TextWriter Error { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether the error stream is redirected.
|
||||
/// </summary>
|
||||
bool IsErrorRedirected { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Current foreground color.
|
||||
/// </summary>
|
||||
ConsoleColor ForegroundColor { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Current background color.
|
||||
/// </summary>
|
||||
ConsoleColor BackgroundColor { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Resets foreground and background color to default values.
|
||||
/// </summary>
|
||||
void ResetColor();
|
||||
}
|
||||
}
|
||||
@@ -3,32 +3,44 @@ using System.IO;
|
||||
|
||||
namespace CliFx.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Implementation of <see cref="IConsole"/> that wraps around <see cref="Console"/>.
|
||||
/// </summary>
|
||||
public class SystemConsole : IConsole
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public TextReader Input => Console.In;
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool IsInputRedirected => Console.IsInputRedirected;
|
||||
|
||||
/// <inheritdoc />
|
||||
public TextWriter Output => Console.Out;
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool IsOutputRedirected => Console.IsOutputRedirected;
|
||||
|
||||
/// <inheritdoc />
|
||||
public TextWriter Error => Console.Error;
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool IsErrorRedirected => Console.IsErrorRedirected;
|
||||
|
||||
/// <inheritdoc />
|
||||
public ConsoleColor ForegroundColor
|
||||
{
|
||||
get => Console.ForegroundColor;
|
||||
set => Console.ForegroundColor = value;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public ConsoleColor BackgroundColor
|
||||
{
|
||||
get => Console.BackgroundColor;
|
||||
set => Console.BackgroundColor = value;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void ResetColor() => Console.ResetColor();
|
||||
}
|
||||
}
|
||||
@@ -3,24 +3,40 @@ using System.IO;
|
||||
|
||||
namespace CliFx.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Implementation of <see cref="IConsole"/> that routes data to specified streams.
|
||||
/// Does not leak to <see cref="Console"/> in any way.
|
||||
/// Provides an isolated instance of <see cref="IConsole"/> which is useful for testing purposes.
|
||||
/// </summary>
|
||||
public class TestConsole : IConsole
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public TextReader Input { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool IsInputRedirected => true;
|
||||
|
||||
/// <inheritdoc />
|
||||
public TextWriter Output { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool IsOutputRedirected => true;
|
||||
|
||||
/// <inheritdoc />
|
||||
public TextWriter Error { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool IsErrorRedirected => true;
|
||||
|
||||
/// <inheritdoc />
|
||||
public ConsoleColor ForegroundColor { get; set; } = ConsoleColor.Gray;
|
||||
|
||||
/// <inheritdoc />
|
||||
public ConsoleColor BackgroundColor { get; set; } = ConsoleColor.Black;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes an instance of <see cref="TestConsole"/>.
|
||||
/// </summary>
|
||||
public TestConsole(TextReader input, TextWriter output, TextWriter error)
|
||||
{
|
||||
Input = input;
|
||||
@@ -28,16 +44,25 @@ namespace CliFx.Services
|
||||
Error = error;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes an instance of <see cref="TestConsole"/> using output stream (stdout) and error stream (stderr).
|
||||
/// Input stream (stdin) is considered empty.
|
||||
/// </summary>
|
||||
public TestConsole(TextWriter output, TextWriter error)
|
||||
: this(TextReader.Null, output, error)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes an instance of <see cref="TestConsole"/> using output stream (stdout).
|
||||
/// Input stream (stdin) and error stream (stderr) are considered empty.
|
||||
/// </summary>
|
||||
public TestConsole(TextWriter output)
|
||||
: this(output, TextWriter.Null)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void ResetColor()
|
||||
{
|
||||
ForegroundColor = ConsoleColor.Gray;
|
||||
|
||||
Reference in New Issue
Block a user