diff --git a/CliFx/Attributes/CommandAttribute.cs b/CliFx/Attributes/CommandAttribute.cs index ce77a7b..7cc3cd5 100644 --- a/CliFx/Attributes/CommandAttribute.cs +++ b/CliFx/Attributes/CommandAttribute.cs @@ -1,20 +1,34 @@ using System; -using CliFx.Internal; namespace CliFx.Attributes { + /// + /// Annotates a type that defines a command. + /// [AttributeUsage(AttributeTargets.Class, Inherited = false)] public class CommandAttribute : Attribute { + /// + /// Command name. + /// public string Name { get; } + /// + /// Command description, which is used in help text. + /// public string Description { get; set; } + /// + /// Initializes an instance of . + /// public CommandAttribute(string name) { Name = name; } + /// + /// Initializes an instance of . + /// public CommandAttribute() : this(null) { diff --git a/CliFx/Attributes/CommandOptionAttribute.cs b/CliFx/Attributes/CommandOptionAttribute.cs index dc09f5e..8860d81 100644 --- a/CliFx/Attributes/CommandOptionAttribute.cs +++ b/CliFx/Attributes/CommandOptionAttribute.cs @@ -2,35 +2,65 @@ namespace CliFx.Attributes { + /// + /// Annotates a property that defines a command option. + /// [AttributeUsage(AttributeTargets.Property)] public class CommandOptionAttribute : Attribute { + /// + /// Option name. + /// public string Name { get; } + /// + /// Option short name. + /// public char? ShortName { get; } + /// + /// Option group name. + /// public string GroupName { get; set; } + /// + /// Whether an option is required. + /// public bool IsRequired { get; set; } + /// + /// Option description, which is used in help text. + /// public string Description { get; set; } + /// + /// Initializes an instance of . + /// public CommandOptionAttribute(string name, char? shortName) { Name = name; ShortName = shortName; } + /// + /// Initializes an instance of . + /// public CommandOptionAttribute(string name, char shortName) : this(name, (char?) shortName) { } + /// + /// Initializes an instance of . + /// public CommandOptionAttribute(string name) : this(name, null) { } + /// + /// Initializes an instance of . + /// public CommandOptionAttribute(char shortName) : this(null, shortName) { diff --git a/CliFx/CliApplication.cs b/CliFx/CliApplication.cs index 79864f6..a262cc5 100644 --- a/CliFx/CliApplication.cs +++ b/CliFx/CliApplication.cs @@ -10,6 +10,9 @@ using CliFx.Services; namespace CliFx { + /// + /// Default implementation of . + /// public partial class CliApplication : ICliApplication { private readonly ApplicationMetadata _applicationMetadata; @@ -22,6 +25,9 @@ namespace CliFx private readonly ICommandInitializer _commandInitializer; private readonly ICommandHelpTextRenderer _commandHelpTextRenderer; + /// + /// Initializes an instance of . + /// public CliApplication(ApplicationMetadata applicationMetadata, IReadOnlyList commandTypes, IConsole console, ICommandInputParser commandInputParser, ICommandSchemaResolver commandSchemaResolver, ICommandFactory commandFactory, ICommandInitializer commandInitializer, ICommandHelpTextRenderer commandHelpTextRenderer) @@ -98,6 +104,7 @@ namespace CliFx return result; } + /// public async Task RunAsync(IReadOnlyList commandLineArguments) { try diff --git a/CliFx/CliApplicationBuilder.cs b/CliFx/CliApplicationBuilder.cs index 79d9221..2fcb1aa 100644 --- a/CliFx/CliApplicationBuilder.cs +++ b/CliFx/CliApplicationBuilder.cs @@ -9,6 +9,9 @@ using CliFx.Services; namespace CliFx { + /// + /// Default implementation of . + /// public class CliApplicationBuilder : ICliApplicationBuilder { private readonly HashSet _commandTypes = new HashSet(); @@ -19,12 +22,14 @@ namespace CliFx private IConsole _console; private ICommandFactory _commandFactory; + /// public ICliApplicationBuilder WithCommand(Type commandType) { _commandTypes.Add(commandType); return this; } + /// public ICliApplicationBuilder WithCommandsFrom(Assembly commandAssembly) { var commandTypes = commandAssembly.ExportedTypes.Where(t => t.Implements(typeof(ICommand))); @@ -35,30 +40,35 @@ namespace CliFx return this; } + /// public ICliApplicationBuilder UseTitle(string title) { _title = title; return this; } - public ICliApplicationBuilder UseExecutableName(string exeName) + /// + public ICliApplicationBuilder UseExecutableName(string executableName) { - _executableName = exeName; + _executableName = executableName; return this; } + /// public ICliApplicationBuilder UseVersionText(string version) { _versionText = version; return this; } + /// public ICliApplicationBuilder UseConsole(IConsole console) { _console = console; return this; } + /// public ICliApplicationBuilder UseCommandFactory(ICommandFactory factory) { _commandFactory = factory; @@ -86,6 +96,7 @@ namespace CliFx UseCommandFactory(new CommandFactory()); } + /// public ICliApplication Build() { // Use defaults for required parameters that were not configured diff --git a/CliFx/Exceptions/CannotConvertCommandOptionException.cs b/CliFx/Exceptions/CannotConvertCommandOptionException.cs index f5d1c1b..d3db503 100644 --- a/CliFx/Exceptions/CannotConvertCommandOptionException.cs +++ b/CliFx/Exceptions/CannotConvertCommandOptionException.cs @@ -2,17 +2,29 @@ namespace CliFx.Exceptions { + /// + /// Thrown when an input command option can't be converted. + /// public class CannotConvertCommandOptionException : CliFxException { + /// + /// Initializes an instance of . + /// public CannotConvertCommandOptionException() { } + /// + /// Initializes an instance of . + /// public CannotConvertCommandOptionException(string message) : base(message) { } + /// + /// Initializes an instance of . + /// public CannotConvertCommandOptionException(string message, Exception innerException) : base(message, innerException) { diff --git a/CliFx/Exceptions/CliFxException.cs b/CliFx/Exceptions/CliFxException.cs index 058e257..6525445 100644 --- a/CliFx/Exceptions/CliFxException.cs +++ b/CliFx/Exceptions/CliFxException.cs @@ -2,18 +2,30 @@ namespace CliFx.Exceptions { + /// + /// Domain exception thrown within CliFx. + /// public abstract class CliFxException : Exception { + /// + /// Initializes an instance of . + /// protected CliFxException(string message) : base(message) { } + /// + /// Initializes an instance of . + /// protected CliFxException(string message, Exception innerException) : base(message, innerException) { } + /// + /// Initializes an instance of . + /// protected CliFxException() { } diff --git a/CliFx/Exceptions/CommandErrorException.cs b/CliFx/Exceptions/CommandErrorException.cs index 28fdd9c..830fcc9 100644 --- a/CliFx/Exceptions/CommandErrorException.cs +++ b/CliFx/Exceptions/CommandErrorException.cs @@ -2,26 +2,45 @@ namespace CliFx.Exceptions { + /// + /// 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. + /// public class CommandErrorException : CliFxException { + /// + /// Process exit code. + /// public int ExitCode { get; } + /// + /// Initializes an instance of . + /// public CommandErrorException(int exitCode, string message, Exception innerException) : base(message, innerException) { ExitCode = exitCode; } + /// + /// Initializes an instance of . + /// public CommandErrorException(int exitCode, Exception innerException) : this(exitCode, null, innerException) { } + /// + /// Initializes an instance of . + /// public CommandErrorException(int exitCode, string message) : this(exitCode, message, null) { } + /// + /// Initializes an instance of . + /// public CommandErrorException(int exitCode) : this(exitCode, null, null) { diff --git a/CliFx/Exceptions/MissingCommandOptionException.cs b/CliFx/Exceptions/MissingCommandOptionException.cs index 679e13e..944c671 100644 --- a/CliFx/Exceptions/MissingCommandOptionException.cs +++ b/CliFx/Exceptions/MissingCommandOptionException.cs @@ -2,17 +2,29 @@ namespace CliFx.Exceptions { + /// + /// Thrown when a required command option was not set. + /// public class MissingCommandOptionException : CliFxException { + /// + /// Initializes an instance of . + /// public MissingCommandOptionException() { } + /// + /// Initializes an instance of . + /// public MissingCommandOptionException(string message) : base(message) { } + /// + /// Initializes an instance of . + /// public MissingCommandOptionException(string message, Exception innerException) : base(message, innerException) { diff --git a/CliFx/Extensions.cs b/CliFx/Extensions.cs index e377310..c9a1a5a 100644 --- a/CliFx/Extensions.cs +++ b/CliFx/Extensions.cs @@ -5,8 +5,14 @@ using CliFx.Services; namespace CliFx { + /// + /// Extensions for . + /// public static class Extensions { + /// + /// Adds multiple commands to the application. + /// public static ICliApplicationBuilder WithCommands(this ICliApplicationBuilder builder, IReadOnlyList commandTypes) { foreach (var commandType in commandTypes) @@ -15,6 +21,9 @@ namespace CliFx return builder; } + /// + /// Adds commands from specified assemblies to the application. + /// public static ICliApplicationBuilder WithCommandsFrom(this ICliApplicationBuilder builder, IReadOnlyList commandAssemblies) { foreach (var commandAssembly in commandAssemblies) @@ -23,9 +32,15 @@ namespace CliFx return builder; } + /// + /// Adds commands from calling assembly to the application. + /// public static ICliApplicationBuilder WithCommandsFromThisAssembly(this ICliApplicationBuilder builder) => builder.WithCommandsFrom(Assembly.GetCallingAssembly()); + /// + /// Configures application to use specified factory method for creating new instances of . + /// public static ICliApplicationBuilder UseCommandFactory(this ICliApplicationBuilder builder, Func factoryMethod) => builder.UseCommandFactory(new DelegateCommandFactory(factoryMethod)); } diff --git a/CliFx/ICliApplication.cs b/CliFx/ICliApplication.cs index d5f4b33..dd4f34e 100644 --- a/CliFx/ICliApplication.cs +++ b/CliFx/ICliApplication.cs @@ -3,8 +3,15 @@ using System.Threading.Tasks; namespace CliFx { + /// + /// Entry point for a command line application. + /// public interface ICliApplication { + /// + /// Runs application with specified command line arguments. + /// Returns exit code. + /// Task RunAsync(IReadOnlyList commandLineArguments); } } \ No newline at end of file diff --git a/CliFx/ICliApplicationBuilder.cs b/CliFx/ICliApplicationBuilder.cs index c12f0c8..5842ce3 100644 --- a/CliFx/ICliApplicationBuilder.cs +++ b/CliFx/ICliApplicationBuilder.cs @@ -4,22 +4,50 @@ using CliFx.Services; namespace CliFx { + /// + /// Builds an instance of . + /// public interface ICliApplicationBuilder { + /// + /// Adds a command of specified type to the application. + /// ICliApplicationBuilder WithCommand(Type commandType); + /// + /// Adds commands from specified assembly to the application. + /// ICliApplicationBuilder WithCommandsFrom(Assembly commandAssembly); + /// + /// Sets application title, which appears in the help text. + /// ICliApplicationBuilder UseTitle(string title); - ICliApplicationBuilder UseExecutableName(string exeName); + /// + /// Sets application executable name, which appears in the help text. + /// + ICliApplicationBuilder UseExecutableName(string executableName); + /// + /// Sets application version text, which appears in the help text and when the user requests version information. + /// ICliApplicationBuilder UseVersionText(string version); + /// + /// Configures application to use specified implementation of . + /// ICliApplicationBuilder UseConsole(IConsole console); + /// + /// Configures application to use specified implementation of . + /// ICliApplicationBuilder UseCommandFactory(ICommandFactory factory); + /// + /// Creates an instance of using configured parameters. + /// Default values are used in place of parameters that were not specified. + /// ICliApplication Build(); } } \ No newline at end of file diff --git a/CliFx/ICommand.cs b/CliFx/ICommand.cs index 6137bd0..9fb2c78 100644 --- a/CliFx/ICommand.cs +++ b/CliFx/ICommand.cs @@ -3,8 +3,15 @@ using CliFx.Services; namespace CliFx { + /// + /// Point of interaction between a user and command line interface. + /// public interface ICommand { + /// + /// Executes command using specified implementation of . + /// This method is called when the command is invoked by a user through command line interface. + /// Task ExecuteAsync(IConsole console); } } \ No newline at end of file diff --git a/CliFx/Models/ApplicationMetadata.cs b/CliFx/Models/ApplicationMetadata.cs index 216f464..8cafd7d 100644 --- a/CliFx/Models/ApplicationMetadata.cs +++ b/CliFx/Models/ApplicationMetadata.cs @@ -1,13 +1,28 @@ namespace CliFx.Models { + /// + /// Metadata associated with an application. + /// public class ApplicationMetadata { + /// + /// Application title. + /// public string Title { get; } + /// + /// Application executable name. + /// public string ExecutableName { get; } + /// + /// Application version text. + /// public string VersionText { get; } + /// + /// Initializes an instance of . + /// public ApplicationMetadata(string title, string executableName, string versionText) { Title = title; diff --git a/CliFx/Models/CommandInput.cs b/CliFx/Models/CommandInput.cs index 4729df8..b637a7b 100644 --- a/CliFx/Models/CommandInput.cs +++ b/CliFx/Models/CommandInput.cs @@ -4,33 +4,55 @@ using CliFx.Internal; namespace CliFx.Models { + /// + /// Parsed command line input. + /// public partial class CommandInput { + /// + /// Specified command name. + /// public string CommandName { get; } + /// + /// Specified options. + /// public IReadOnlyList Options { get; } + /// + /// Initializes an instance of . + /// public CommandInput(string commandName, IReadOnlyList options) { CommandName = commandName; Options = options; } + /// + /// Initializes an instance of . + /// public CommandInput(IReadOnlyList options) : this(null, options) { } + /// + /// Initializes an instance of . + /// public CommandInput(string commandName) : this(commandName, new CommandOptionInput[0]) { } + /// + /// Initializes an instance of . + /// public CommandInput() : this(null, new CommandOptionInput[0]) { } + /// public override string ToString() { var buffer = new StringBuilder(); @@ -53,6 +75,9 @@ namespace CliFx.Models public partial class CommandInput { + /// + /// Empty input. + /// public static CommandInput Empty { get; } = new CommandInput(); } } \ No newline at end of file diff --git a/CliFx/Models/CommandOptionInput.cs b/CliFx/Models/CommandOptionInput.cs index 50e8080..ded3eb3 100644 --- a/CliFx/Models/CommandOptionInput.cs +++ b/CliFx/Models/CommandOptionInput.cs @@ -3,28 +3,47 @@ using System.Text; namespace CliFx.Models { + /// + /// Parsed option from command line input. + /// public class CommandOptionInput { + /// + /// Specified option alias. + /// public string Alias { get; } + /// + /// Specified values. + /// public IReadOnlyList Values { get; } + /// + /// Initializes an instance of . + /// public CommandOptionInput(string alias, IReadOnlyList values) { Alias = alias; Values = values; } + /// + /// Initializes an instance of . + /// public CommandOptionInput(string alias, string value) : this(alias, new[] {value}) { } + /// + /// Initializes an instance of . + /// public CommandOptionInput(string alias) : this(alias, new string[0]) { } + /// public override string ToString() { var buffer = new StringBuilder(); diff --git a/CliFx/Models/CommandOptionSchema.cs b/CliFx/Models/CommandOptionSchema.cs index 35b3dfc..2fedebd 100644 --- a/CliFx/Models/CommandOptionSchema.cs +++ b/CliFx/Models/CommandOptionSchema.cs @@ -4,20 +4,44 @@ using CliFx.Internal; namespace CliFx.Models { + /// + /// Schema of a defined command option. + /// public class CommandOptionSchema { + /// + /// Underlying property. + /// public PropertyInfo Property { get; } + /// + /// Option name. + /// public string Name { get; } + /// + /// Option short name. + /// public char? ShortName { get; } + /// + /// Option group name. + /// public string GroupName { get; } + /// + /// Whether an option is required. + /// public bool IsRequired { get; } + /// + /// Option description. + /// public string Description { get; } + /// + /// Initializes an instance of . + /// public CommandOptionSchema(PropertyInfo property, string name, char? shortName, string groupName, bool isRequired, string description) { @@ -29,6 +53,7 @@ namespace CliFx.Models Description = description; } + /// public override string ToString() { var buffer = new StringBuilder(); diff --git a/CliFx/Models/CommandSchema.cs b/CliFx/Models/CommandSchema.cs index 01b6ed8..c59d073 100644 --- a/CliFx/Models/CommandSchema.cs +++ b/CliFx/Models/CommandSchema.cs @@ -5,16 +5,34 @@ using CliFx.Internal; namespace CliFx.Models { + /// + /// Schema of a defined command. + /// public class CommandSchema { + /// + /// Underlying type. + /// public Type Type { get; } + /// + /// Command name. + /// public string Name { get; } + /// + /// Command description. + /// public string Description { get; } + /// + /// Command options. + /// public IReadOnlyList Options { get; } + /// + /// Initializes an instance of . + /// public CommandSchema(Type type, string name, string description, IReadOnlyList options) { Type = type; @@ -23,6 +41,7 @@ namespace CliFx.Models Options = options; } + /// public override string ToString() { var buffer = new StringBuilder(); diff --git a/CliFx/Models/Extensions.cs b/CliFx/Models/Extensions.cs index d9c727b..a3d6e52 100644 --- a/CliFx/Models/Extensions.cs +++ b/CliFx/Models/Extensions.cs @@ -5,10 +5,19 @@ using CliFx.Internal; namespace CliFx.Models { + /// + /// Extensions for . + /// public static class Extensions { + /// + /// Gets whether a command was specified in the input. + /// public static bool IsCommandSpecified(this CommandInput commandInput) => !commandInput.CommandName.IsNullOrWhiteSpace(); + /// + /// Gets whether help was requested in the input. + /// 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); } + /// + /// Gets whether version information was requested in the input. + /// 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); } + /// + /// Gets whether this command is the default command, i.e. without a name. + /// public static bool IsDefault(this CommandSchema commandSchema) => commandSchema.Name.IsNullOrWhiteSpace(); + /// + /// Finds a command that has specified name, or null if not found. + /// public static CommandSchema FindByName(this IReadOnlyList commandSchemas, string commandName) => commandSchemas.FirstOrDefault(c => string.Equals(c.Name, commandName, StringComparison.OrdinalIgnoreCase)); + /// + /// Finds parent command to the command that has specified name, or null if not found. + /// public static CommandSchema FindParent(this IReadOnlyList 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()); } + /// + /// Finds an option that matches specified alias, or null if not found. + /// public static CommandOptionSchema FindByAlias(this IReadOnlyList optionSchemas, string alias) { foreach (var optionSchema in optionSchemas) diff --git a/CliFx/Models/HelpTextSource.cs b/CliFx/Models/HelpTextSource.cs index 5f09488..556f522 100644 --- a/CliFx/Models/HelpTextSource.cs +++ b/CliFx/Models/HelpTextSource.cs @@ -2,14 +2,29 @@ namespace CliFx.Models { + /// + /// Source information used to generate help text. + /// public class HelpTextSource { + /// + /// Application metadata. + /// public ApplicationMetadata ApplicationMetadata { get; } + /// + /// Schemas of commands available in the application. + /// public IReadOnlyList AvailableCommandSchemas { get; } + /// + /// Schema of the command for which help text is to be generated. + /// public CommandSchema TargetCommandSchema { get; } + /// + /// Initializes an instance of . + /// public HelpTextSource(ApplicationMetadata applicationMetadata, IReadOnlyList availableCommandSchemas, CommandSchema targetCommandSchema) diff --git a/CliFx/Services/CommandFactory.cs b/CliFx/Services/CommandFactory.cs index 9092299..98b36fb 100644 --- a/CliFx/Services/CommandFactory.cs +++ b/CliFx/Services/CommandFactory.cs @@ -2,8 +2,12 @@ namespace CliFx.Services { + /// + /// Default implementation of . + /// public class CommandFactory : ICommandFactory { + /// public ICommand CreateCommand(Type commandType) => (ICommand) Activator.CreateInstance(commandType); } } \ No newline at end of file diff --git a/CliFx/Services/CommandHelpTextRenderer.cs b/CliFx/Services/CommandHelpTextRenderer.cs index 6f6ddfe..1f80d90 100644 --- a/CliFx/Services/CommandHelpTextRenderer.cs +++ b/CliFx/Services/CommandHelpTextRenderer.cs @@ -6,8 +6,12 @@ using CliFx.Models; namespace CliFx.Services { + /// + /// Default implementation of . + /// public partial class CommandHelpTextRenderer : ICommandHelpTextRenderer { + /// public void RenderHelpText(IConsole console, HelpTextSource source) => new Impl(console, source).RenderHelpText(); } diff --git a/CliFx/Services/CommandInitializer.cs b/CliFx/Services/CommandInitializer.cs index 101bdc8..8f82c01 100644 --- a/CliFx/Services/CommandInitializer.cs +++ b/CliFx/Services/CommandInitializer.cs @@ -7,20 +7,30 @@ using CliFx.Models; namespace CliFx.Services { + /// + /// Default implementation of . + /// public class CommandInitializer : ICommandInitializer { private readonly ICommandOptionInputConverter _commandOptionInputConverter; + /// + /// Initializes an instance of . + /// public CommandInitializer(ICommandOptionInputConverter commandOptionInputConverter) { _commandOptionInputConverter = commandOptionInputConverter; } + /// + /// Initializes an instance of . + /// public CommandInitializer() : this(new CommandOptionInputConverter()) { } + /// public void InitializeCommand(ICommand command, CommandSchema schema, CommandInput input) { // Set command options diff --git a/CliFx/Services/CommandInputParser.cs b/CliFx/Services/CommandInputParser.cs index 24185d3..7a8dfad 100644 --- a/CliFx/Services/CommandInputParser.cs +++ b/CliFx/Services/CommandInputParser.cs @@ -6,9 +6,13 @@ using CliFx.Models; namespace CliFx.Services { + /// + /// Default implementation of . + /// public class CommandInputParser : ICommandInputParser { // TODO: refactor + /// public CommandInput ParseInput(IReadOnlyList commandLineArguments) { // Initialize command name placeholder diff --git a/CliFx/Services/CommandOptionInputConverter.cs b/CliFx/Services/CommandOptionInputConverter.cs index 15a8334..11932a9 100644 --- a/CliFx/Services/CommandOptionInputConverter.cs +++ b/CliFx/Services/CommandOptionInputConverter.cs @@ -8,15 +8,24 @@ using CliFx.Models; namespace CliFx.Services { + /// + /// Default implementation of . + /// public class CommandOptionInputConverter : ICommandOptionInputConverter { private readonly IFormatProvider _formatProvider; + /// + /// Initializes an instance of . + /// public CommandOptionInputConverter(IFormatProvider formatProvider) { _formatProvider = formatProvider; } + /// + /// Initializes an instance of . + /// public CommandOptionInputConverter() : this(CultureInfo.InvariantCulture) { @@ -232,6 +241,7 @@ namespace CliFx.Services } // TODO: refactor this + /// public object ConvertOption(CommandOptionInput option, Type targetType) { if (targetType != typeof(string) && targetType.IsEnumerable()) diff --git a/CliFx/Services/CommandSchemaResolver.cs b/CliFx/Services/CommandSchemaResolver.cs index 554939c..4c8551d 100644 --- a/CliFx/Services/CommandSchemaResolver.cs +++ b/CliFx/Services/CommandSchemaResolver.cs @@ -7,6 +7,9 @@ using CliFx.Models; namespace CliFx.Services { + /// + /// Default implementation of . + /// 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 + /// public CommandSchema GetCommandSchema(Type commandType) { if (!commandType.Implements(typeof(ICommand))) diff --git a/CliFx/Services/DelegateCommandFactory.cs b/CliFx/Services/DelegateCommandFactory.cs index 008c4d6..0d70df7 100644 --- a/CliFx/Services/DelegateCommandFactory.cs +++ b/CliFx/Services/DelegateCommandFactory.cs @@ -2,15 +2,22 @@ namespace CliFx.Services { + /// + /// Implementation of that uses a factory method to create commands. + /// public class DelegateCommandFactory : ICommandFactory { private readonly Func _factoryMethod; + /// + /// Initializes an instance of . + /// public DelegateCommandFactory(Func factoryMethod) { _factoryMethod = factoryMethod; } + /// public ICommand CreateCommand(Type commandType) => _factoryMethod(commandType); } } \ No newline at end of file diff --git a/CliFx/Services/Extensions.cs b/CliFx/Services/Extensions.cs index 27596d0..a962896 100644 --- a/CliFx/Services/Extensions.cs +++ b/CliFx/Services/Extensions.cs @@ -5,12 +5,20 @@ using CliFx.Models; namespace CliFx.Services { + /// + /// Extensions for + /// public static class Extensions { + /// + /// Resolves command schemas for commands of specified types. + /// public static IReadOnlyList GetCommandSchemas(this ICommandSchemaResolver resolver, - IReadOnlyList commandTypes) => - commandTypes.Select(resolver.GetCommandSchema).ToArray(); + IReadOnlyList commandTypes) => commandTypes.Select(resolver.GetCommandSchema).ToArray(); + /// + /// Sets console foreground color, executes specified action, and sets the color back to the original value. + /// 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; } + /// + /// Sets console background color, executes specified action, and sets the color back to the original value. + /// 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; } + /// + /// Sets console foreground and background colors, executes specified action, and sets the colors back to the original values. + /// public static void WithColors(this IConsole console, ConsoleColor foregroundColor, ConsoleColor backgroundColor, Action action) => console.WithForegroundColor(foregroundColor, () => console.WithBackgroundColor(backgroundColor, action)); } diff --git a/CliFx/Services/ICommandFactory.cs b/CliFx/Services/ICommandFactory.cs index b952318..cf598b5 100644 --- a/CliFx/Services/ICommandFactory.cs +++ b/CliFx/Services/ICommandFactory.cs @@ -2,8 +2,14 @@ namespace CliFx.Services { + /// + /// Initializes new instances of . + /// public interface ICommandFactory { + /// + /// Initializes an instance of of specified type. + /// ICommand CreateCommand(Type commandType); } } \ No newline at end of file diff --git a/CliFx/Services/ICommandHelpTextRenderer.cs b/CliFx/Services/ICommandHelpTextRenderer.cs index b7f67df..7dcd632 100644 --- a/CliFx/Services/ICommandHelpTextRenderer.cs +++ b/CliFx/Services/ICommandHelpTextRenderer.cs @@ -2,8 +2,14 @@ namespace CliFx.Services { + /// + /// Renders help text to the console. + /// public interface ICommandHelpTextRenderer { + /// + /// Renders help text using specified console and source information. + /// void RenderHelpText(IConsole console, HelpTextSource source); } } \ No newline at end of file diff --git a/CliFx/Services/ICommandInitializer.cs b/CliFx/Services/ICommandInitializer.cs index 07ee0cc..bfd7ed1 100644 --- a/CliFx/Services/ICommandInitializer.cs +++ b/CliFx/Services/ICommandInitializer.cs @@ -2,8 +2,14 @@ namespace CliFx.Services { + /// + /// Populates instances with input according to its schema. + /// public interface ICommandInitializer { + /// + /// Populates an instance of with specified input according to specified schema. + /// void InitializeCommand(ICommand command, CommandSchema schema, CommandInput input); } } \ No newline at end of file diff --git a/CliFx/Services/ICommandInputParser.cs b/CliFx/Services/ICommandInputParser.cs index def430e..6585d09 100644 --- a/CliFx/Services/ICommandInputParser.cs +++ b/CliFx/Services/ICommandInputParser.cs @@ -3,8 +3,14 @@ using CliFx.Models; namespace CliFx.Services { + /// + /// Parses command line arguments. + /// public interface ICommandInputParser { + /// + /// Parses specified command line arguments. + /// CommandInput ParseInput(IReadOnlyList commandLineArguments); } } \ No newline at end of file diff --git a/CliFx/Services/ICommandOptionInputConverter.cs b/CliFx/Services/ICommandOptionInputConverter.cs index 40b8c10..cdfb104 100644 --- a/CliFx/Services/ICommandOptionInputConverter.cs +++ b/CliFx/Services/ICommandOptionInputConverter.cs @@ -3,8 +3,14 @@ using CliFx.Models; namespace CliFx.Services { + /// + /// Converts input command options. + /// public interface ICommandOptionInputConverter { + /// + /// Converts an option to specified target type. + /// object ConvertOption(CommandOptionInput option, Type targetType); } } \ No newline at end of file diff --git a/CliFx/Services/ICommandSchemaResolver.cs b/CliFx/Services/ICommandSchemaResolver.cs index ed82aad..3ffbccc 100644 --- a/CliFx/Services/ICommandSchemaResolver.cs +++ b/CliFx/Services/ICommandSchemaResolver.cs @@ -3,8 +3,14 @@ using CliFx.Models; namespace CliFx.Services { + /// + /// Resolves command schemas. + /// public interface ICommandSchemaResolver { + /// + /// Resolves schema of a command of specified type. + /// CommandSchema GetCommandSchema(Type commandType); } } \ No newline at end of file diff --git a/CliFx/Services/IConsole.cs b/CliFx/Services/IConsole.cs index 8210aa7..6d92bf2 100644 --- a/CliFx/Services/IConsole.cs +++ b/CliFx/Services/IConsole.cs @@ -3,24 +3,54 @@ using System.IO; namespace CliFx.Services { + /// + /// Abstraction for interacting with the console. + /// public interface IConsole { + /// + /// Input stream (stdin). + /// TextReader Input { get; } + /// + /// Whether the input stream is redirected. + /// bool IsInputRedirected { get; } + /// + /// Output stream (stdout). + /// TextWriter Output { get; } + /// + /// Whether the output stream is redirected. + /// bool IsOutputRedirected { get; } + /// + /// Error stream (stderr). + /// TextWriter Error { get; } + /// + /// Whether the error stream is redirected. + /// bool IsErrorRedirected { get; } + /// + /// Current foreground color. + /// ConsoleColor ForegroundColor { get; set; } + /// + /// Current background color. + /// ConsoleColor BackgroundColor { get; set; } + /// + /// Resets foreground and background color to default values. + /// void ResetColor(); } } \ No newline at end of file diff --git a/CliFx/Services/SystemConsole.cs b/CliFx/Services/SystemConsole.cs index f723908..193b3fd 100644 --- a/CliFx/Services/SystemConsole.cs +++ b/CliFx/Services/SystemConsole.cs @@ -3,32 +3,44 @@ using System.IO; namespace CliFx.Services { + /// + /// Implementation of that wraps around . + /// public class SystemConsole : IConsole { + /// public TextReader Input => Console.In; + /// public bool IsInputRedirected => Console.IsInputRedirected; + /// public TextWriter Output => Console.Out; + /// public bool IsOutputRedirected => Console.IsOutputRedirected; + /// public TextWriter Error => Console.Error; + /// public bool IsErrorRedirected => Console.IsErrorRedirected; + /// public ConsoleColor ForegroundColor { get => Console.ForegroundColor; set => Console.ForegroundColor = value; } + /// public ConsoleColor BackgroundColor { get => Console.BackgroundColor; set => Console.BackgroundColor = value; } + /// public void ResetColor() => Console.ResetColor(); } } \ No newline at end of file diff --git a/CliFx/Services/TestConsole.cs b/CliFx/Services/TestConsole.cs index 331f0b4..5beec51 100644 --- a/CliFx/Services/TestConsole.cs +++ b/CliFx/Services/TestConsole.cs @@ -3,24 +3,40 @@ using System.IO; namespace CliFx.Services { + /// + /// Implementation of that routes data to specified streams. + /// Does not leak to in any way. + /// Provides an isolated instance of which is useful for testing purposes. + /// public class TestConsole : IConsole { + /// public TextReader Input { get; } + /// public bool IsInputRedirected => true; + /// public TextWriter Output { get; } + /// public bool IsOutputRedirected => true; + /// public TextWriter Error { get; } + /// public bool IsErrorRedirected => true; + /// public ConsoleColor ForegroundColor { get; set; } = ConsoleColor.Gray; + /// public ConsoleColor BackgroundColor { get; set; } = ConsoleColor.Black; + /// + /// Initializes an instance of . + /// public TestConsole(TextReader input, TextWriter output, TextWriter error) { Input = input; @@ -28,16 +44,25 @@ namespace CliFx.Services Error = error; } + /// + /// Initializes an instance of using output stream (stdout) and error stream (stderr). + /// Input stream (stdin) is considered empty. + /// public TestConsole(TextWriter output, TextWriter error) : this(TextReader.Null, output, error) { } + /// + /// Initializes an instance of using output stream (stdout). + /// Input stream (stdin) and error stream (stderr) are considered empty. + /// public TestConsole(TextWriter output) : this(output, TextWriter.Null) { } + /// public void ResetColor() { ForegroundColor = ConsoleColor.Gray;