diff --git a/CliFx.Tests.Dummy/Commands/AddCommand.cs b/CliFx.Tests.Dummy/Commands/AddCommand.cs index 66634f1..dea9b7f 100644 --- a/CliFx.Tests.Dummy/Commands/AddCommand.cs +++ b/CliFx.Tests.Dummy/Commands/AddCommand.cs @@ -7,10 +7,10 @@ using CliFx.Models; namespace CliFx.Tests.Dummy.Commands { - [Command("add")] + [Command("add", Description = "Calculate the sum of all input values.")] public class AddCommand : Command { - [CommandOption("values", 'v', IsRequired = true, Description = "Values.")] + [CommandOption("values", 'v', IsRequired = true, Description = "Input values.")] public IReadOnlyList Values { get; set; } public override ExitCode Execute() diff --git a/CliFx.Tests.Dummy/Commands/LogCommand.cs b/CliFx.Tests.Dummy/Commands/LogCommand.cs index 690b434..6d178a3 100644 --- a/CliFx.Tests.Dummy/Commands/LogCommand.cs +++ b/CliFx.Tests.Dummy/Commands/LogCommand.cs @@ -2,10 +2,11 @@ using System.Globalization; using CliFx.Attributes; using CliFx.Models; +using CliFx.Services; namespace CliFx.Tests.Dummy.Commands { - [Command("log")] + [Command("log", Description = "Calculate the logarithm of a value.")] public class LogCommand : Command { [CommandOption("value", 'v', IsRequired = true, Description = "Value whose logarithm is to be found.")] diff --git a/CliFx/Attributes/CommandAttribute.cs b/CliFx/Attributes/CommandAttribute.cs index dbccc97..4362401 100644 --- a/CliFx/Attributes/CommandAttribute.cs +++ b/CliFx/Attributes/CommandAttribute.cs @@ -7,6 +7,8 @@ namespace CliFx.Attributes { public string Name { get; } + public string Description { get; set; } + public CommandAttribute(string name) { Name = name; diff --git a/CliFx/Attributes/DefaultCommandAttribute.cs b/CliFx/Attributes/DefaultCommandAttribute.cs index 43195cd..be22488 100644 --- a/CliFx/Attributes/DefaultCommandAttribute.cs +++ b/CliFx/Attributes/DefaultCommandAttribute.cs @@ -3,7 +3,11 @@ namespace CliFx.Attributes { [AttributeUsage(AttributeTargets.Class, Inherited = false)] - public class DefaultCommandAttribute : Attribute + public class DefaultCommandAttribute : CommandAttribute { + public DefaultCommandAttribute() + : base(null) + { + } } } \ No newline at end of file diff --git a/CliFx/Internal/CommandType.cs b/CliFx/Internal/CommandType.cs index 520fcfa..d1dbaeb 100644 --- a/CliFx/Internal/CommandType.cs +++ b/CliFx/Internal/CommandType.cs @@ -14,17 +14,19 @@ namespace CliFx.Internal public bool IsDefault { get; } - public CommandType(Type type, string name, bool isDefault) + public string Description { get; } + + public IReadOnlyList Options { get; } + + public CommandType(Type type, string name, bool isDefault, string description, IReadOnlyList options) { _type = type; Name = name; IsDefault = isDefault; + Description = description; + Options = options; } - public IEnumerable GetOptionProperties() => _type.GetProperties() - .Where(CommandOptionProperty.IsValid) - .Select(CommandOptionProperty.Initialize); - public Command Activate() => (Command) Activator.CreateInstance(_type); } @@ -41,10 +43,18 @@ namespace CliFx.Internal if (!IsValid(type)) throw new InvalidOperationException($"[{type.Name}] is not a valid command type."); - var name = type.GetCustomAttribute()?.Name; - var isDefault = type.IsDefined(typeof(DefaultCommandAttribute)); + var attribute = type.GetCustomAttribute(); - return new CommandType(type, name, isDefault); + var name = attribute.Name; + var isDefault = attribute is DefaultCommandAttribute; + var description = attribute.Description; + + var options = type.GetProperties() + .Where(CommandOptionProperty.IsValid) + .Select(CommandOptionProperty.Initialize) + .ToArray(); + + return new CommandType(type, name, isDefault, description, options); } public static IEnumerable GetCommandTypes(IEnumerable types) => types.Where(IsValid).Select(Initialize); diff --git a/CliFx/Services/CommandResolver.cs b/CliFx/Services/CommandResolver.cs index f37f891..698a41b 100644 --- a/CliFx/Services/CommandResolver.cs +++ b/CliFx/Services/CommandResolver.cs @@ -84,7 +84,7 @@ namespace CliFx.Services var command = commandType.Activate(); // Set command options - foreach (var property in commandType.GetOptionProperties()) + foreach (var property in commandType.Options) { // Get option for this property var option = optionSet.GetOptionOrDefault(property.Name, property.ShortName); @@ -95,7 +95,7 @@ namespace CliFx.Services var convertedValue = _commandOptionConverter.ConvertOption(option, property.Type); property.SetValue(command, convertedValue); } - // If the property is missing but it's required - throw + // If the property is required but it's missing - throw else if (property.IsRequired) { throw new CommandResolveException($"Can't resolve command because required property [{property.Name}] is not set.");