From a322632e468bd3bcf64798a2b6c04c1b16de8732 Mon Sep 17 00:00:00 2001 From: Alexey Golub Date: Tue, 13 Aug 2019 18:00:26 +0300 Subject: [PATCH] Change ICommandHelpTextRenderer --- CliFx/CliApplication.cs | 6 +- CliFx/CliApplicationBuilder.cs | 2 +- CliFx/Models/HelpTextSource.cs | 22 + CliFx/Services/CommandHelpTextRenderer.cs | 447 +++++++++++---------- CliFx/Services/ICommandHelpTextRenderer.cs | 6 +- 5 files changed, 258 insertions(+), 225 deletions(-) create mode 100644 CliFx/Models/HelpTextSource.cs diff --git a/CliFx/CliApplication.cs b/CliFx/CliApplication.cs index 876a5dd..fd8fad0 100644 --- a/CliFx/CliApplication.cs +++ b/CliFx/CliApplication.cs @@ -79,7 +79,8 @@ namespace CliFx } // Show help - _commandHelpTextRenderer.RenderHelpText(_applicationMetadata, availableCommandSchemas, parentCommandSchema); + var helpTextSource = new HelpTextSource(_applicationMetadata, availableCommandSchemas, parentCommandSchema); + _commandHelpTextRenderer.RenderHelpText(_console, helpTextSource); return isError ? -1 : 0; } @@ -95,7 +96,8 @@ namespace CliFx // Show help if it was requested if (commandInput.IsHelpRequested()) { - _commandHelpTextRenderer.RenderHelpText(_applicationMetadata, availableCommandSchemas, matchingCommandSchema); + var helpTextSource = new HelpTextSource(_applicationMetadata, availableCommandSchemas, matchingCommandSchema); + _commandHelpTextRenderer.RenderHelpText(_console, helpTextSource); return 0; } diff --git a/CliFx/CliApplicationBuilder.cs b/CliFx/CliApplicationBuilder.cs index dfadce0..f60c6a0 100644 --- a/CliFx/CliApplicationBuilder.cs +++ b/CliFx/CliApplicationBuilder.cs @@ -83,7 +83,7 @@ namespace CliFx return new CliApplication(metadata, commandTypes, console, new CommandInputParser(), new CommandSchemaResolver(), - commandFactory, new CommandInitializer(), new CommandHelpTextRenderer(console)); + commandFactory, new CommandInitializer(), new CommandHelpTextRenderer()); } } } \ No newline at end of file diff --git a/CliFx/Models/HelpTextSource.cs b/CliFx/Models/HelpTextSource.cs new file mode 100644 index 0000000..5f09488 --- /dev/null +++ b/CliFx/Models/HelpTextSource.cs @@ -0,0 +1,22 @@ +using System.Collections.Generic; + +namespace CliFx.Models +{ + public class HelpTextSource + { + public ApplicationMetadata ApplicationMetadata { get; } + + public IReadOnlyList AvailableCommandSchemas { get; } + + public CommandSchema TargetCommandSchema { get; } + + public HelpTextSource(ApplicationMetadata applicationMetadata, + IReadOnlyList availableCommandSchemas, + CommandSchema targetCommandSchema) + { + ApplicationMetadata = applicationMetadata; + AvailableCommandSchemas = availableCommandSchemas; + TargetCommandSchema = targetCommandSchema; + } + } +} \ No newline at end of file diff --git a/CliFx/Services/CommandHelpTextRenderer.cs b/CliFx/Services/CommandHelpTextRenderer.cs index b982adb..6f6ddfe 100644 --- a/CliFx/Services/CommandHelpTextRenderer.cs +++ b/CliFx/Services/CommandHelpTextRenderer.cs @@ -8,249 +8,260 @@ namespace CliFx.Services { public partial class CommandHelpTextRenderer : ICommandHelpTextRenderer { - private readonly IConsole _console; + public void RenderHelpText(IConsole console, HelpTextSource source) => new Impl(console, source).RenderHelpText(); + } - private bool _isEmpty = true; - private int _position; - - public CommandHelpTextRenderer(IConsole console) + public partial class CommandHelpTextRenderer + { + private class Impl { - _console = console; - } + private readonly IConsole _console; + private readonly HelpTextSource _source; - private void Render(string text) - { - _console.Output.Write(text); + private bool _isEmpty = true; + private int _position; - _isEmpty = false; - _position += text.Length; - } - - private void RenderNewLine() - { - _console.Output.WriteLine(); - - _isEmpty = false; - _position = 0; - } - - private void RenderIndent(int spaces = 2) => Render(' '.Repeat(spaces)); - - private void RenderColumnIndent(int spaces = 20, int margin = 2) - { - if (_position + margin >= spaces) + public Impl(IConsole console, HelpTextSource source) { - RenderNewLine(); - RenderIndent(spaces); + _console = console; + _source = source; } - else + + private void Render(string text) { - RenderIndent(spaces - _position); + _console.Output.Write(text); + + _isEmpty = false; + _position += text.Length; } - } - private void Render(string text, ConsoleColor foregroundColor) => - _console.WithForegroundColor(foregroundColor, () => Render(text)); - - private void Render(string text, ConsoleColor foregroundColor, ConsoleColor backgroundColor) => - _console.WithColors(foregroundColor, backgroundColor, () => Render(text)); - - private void RenderHeader(string text) - { - Render(text, ConsoleColor.Black, ConsoleColor.DarkGray); - RenderNewLine(); - } - - private void RenderApplicationInfo(ApplicationMetadata applicationMetadata, CommandSchema commandSchema) - { - if (!commandSchema.IsDefault()) - return; - - // Margin - if (!_isEmpty) - RenderNewLine(); - - // Title and version - Render($"{applicationMetadata.Title} v{applicationMetadata.VersionText}", ConsoleColor.Yellow); - RenderNewLine(); - } - - private void RenderDescription(CommandSchema commandSchema) - { - if (commandSchema.Description.IsNullOrWhiteSpace()) - return; - - // Margin - if (!_isEmpty) - RenderNewLine(); - - // Header - RenderHeader("Description"); - - // Description - RenderIndent(); - Render(commandSchema.Description); - RenderNewLine(); - } - - private void RenderUsage(ApplicationMetadata applicationMetadata, CommandSchema commandSchema, - IReadOnlyList childCommandSchemas) - { - // Margin - if (!_isEmpty) - RenderNewLine(); - - // Header - RenderHeader("Usage"); - - // Exe name - RenderIndent(); - Render(applicationMetadata.ExecutableName); - - // Command name - if (!commandSchema.IsDefault()) + private void RenderNewLine() { + _console.Output.WriteLine(); + + _isEmpty = false; + _position = 0; + } + + private void RenderIndent(int spaces = 2) => Render(' '.Repeat(spaces)); + + private void RenderColumnIndent(int spaces = 20, int margin = 2) + { + if (_position + margin >= spaces) + { + RenderNewLine(); + RenderIndent(spaces); + } + else + { + RenderIndent(spaces - _position); + } + } + + private void Render(string text, ConsoleColor foregroundColor) => + _console.WithForegroundColor(foregroundColor, () => Render(text)); + + private void Render(string text, ConsoleColor foregroundColor, ConsoleColor backgroundColor) => + _console.WithColors(foregroundColor, backgroundColor, () => Render(text)); + + private void RenderHeader(string text) + { + Render(text, ConsoleColor.Black, ConsoleColor.DarkGray); + RenderNewLine(); + } + + private void RenderApplicationInfo() + { + if (!_source.TargetCommandSchema.IsDefault()) + return; + + // Margin + if (!_isEmpty) + RenderNewLine(); + + // Title + Render(_source.ApplicationMetadata.Title, ConsoleColor.Yellow); Render(" "); - Render(commandSchema.Name, ConsoleColor.Cyan); + Render(_source.ApplicationMetadata.VersionText, ConsoleColor.Yellow); + RenderNewLine(); } - // Child command - if (childCommandSchemas.Any()) + private void RenderDescription() { + if (_source.TargetCommandSchema.Description.IsNullOrWhiteSpace()) + return; + + // Margin + if (!_isEmpty) + RenderNewLine(); + + // Header + RenderHeader("Description"); + + // Description + RenderIndent(); + Render(_source.TargetCommandSchema.Description); + RenderNewLine(); + } + + private void RenderUsage() + { + // Margin + if (!_isEmpty) + RenderNewLine(); + + // Header + RenderHeader("Usage"); + + // Exe name + RenderIndent(); + Render(_source.ApplicationMetadata.ExecutableName); + + // Command name + if (!_source.TargetCommandSchema.IsDefault()) + { + Render(" "); + Render(_source.TargetCommandSchema.Name, ConsoleColor.Cyan); + } + + // Child command + if (GetChildCommandSchemas(_source.AvailableCommandSchemas, _source.TargetCommandSchema).Any()) + { + Render(" "); + Render("[command]", ConsoleColor.Cyan); + } + + // Options + Render(" "); + Render("[options]", ConsoleColor.White); + RenderNewLine(); + } + + private void RenderOptions() + { + var options = new List(); + options.AddRange(_source.TargetCommandSchema.Options); + + options.Add(new CommandOptionSchema(null, "help", 'h', null, false, "Shows help text.")); + + if (_source.TargetCommandSchema.IsDefault()) + options.Add(new CommandOptionSchema(null, "version", null, null, false, "Shows application version.")); + + // Margin + if (!_isEmpty) + RenderNewLine(); + + // Header + RenderHeader("Options"); + + // Options + foreach (var option in options) + { + RenderIndent(); + + // Short name + if (option.ShortName != null) + { + Render($"-{option.ShortName}", ConsoleColor.White); + } + + // Delimiter + if (!option.Name.IsNullOrWhiteSpace() && option.ShortName != null) + { + Render("|"); + } + + // Name + if (!option.Name.IsNullOrWhiteSpace()) + { + Render($"--{option.Name}", ConsoleColor.White); + } + + // Description + if (!option.Description.IsNullOrWhiteSpace()) + { + RenderColumnIndent(); + Render(option.Description); + } + + RenderNewLine(); + } + } + + private void RenderChildCommands() + { + var childCommandSchemas = GetChildCommandSchemas(_source.AvailableCommandSchemas, _source.TargetCommandSchema).ToArray(); + + if (!childCommandSchemas.Any()) + return; + + // Margin + if (!_isEmpty) + RenderNewLine(); + + // Header + RenderHeader("Commands"); + + // Child commands + foreach (var childCommandSchema in childCommandSchemas) + { + var relativeCommandName = GetRelativeCommandName(childCommandSchema, _source.TargetCommandSchema); + + // Name + RenderIndent(); + Render(relativeCommandName, ConsoleColor.Cyan); + + // Description + if (!childCommandSchema.Description.IsNullOrWhiteSpace()) + { + RenderColumnIndent(); + Render(childCommandSchema.Description); + } + + RenderNewLine(); + } + + // Margin + RenderNewLine(); + + // Child command help tip + Render("You can run `"); + Render(_source.ApplicationMetadata.ExecutableName); + + if (!_source.TargetCommandSchema.IsDefault()) + { + Render(" "); + Render(_source.TargetCommandSchema.Name, ConsoleColor.Cyan); + } + Render(" "); Render("[command]", ConsoleColor.Cyan); - } - // Options - Render(" "); - Render("[options]", ConsoleColor.White); - RenderNewLine(); - } - - private void RenderOptions(CommandSchema commandSchema) - { - var options = new List(); - options.AddRange(commandSchema.Options); - - options.Add(new CommandOptionSchema(null, "help", 'h', null, false, "Shows help text.")); - - if (commandSchema.IsDefault()) - options.Add(new CommandOptionSchema(null, "version", null, null, false, "Shows application version.")); - - // Margin - if (!_isEmpty) - RenderNewLine(); - - // Header - RenderHeader("Options"); - - // Options - foreach (var option in options) - { - RenderIndent(); - - // Short name - if (option.ShortName != null) - { - Render($"-{option.ShortName}", ConsoleColor.White); - } - - // Delimiter - if (!option.Name.IsNullOrWhiteSpace() && option.ShortName != null) - { - Render("|"); - } - - // Name - if (!option.Name.IsNullOrWhiteSpace()) - { - Render($"--{option.Name}", ConsoleColor.White); - } - - // Description - if (!option.Description.IsNullOrWhiteSpace()) - { - RenderColumnIndent(); - Render(option.Description); - } - - RenderNewLine(); - } - } - - private void RenderChildCommands(ApplicationMetadata applicationMetadata, CommandSchema commandSchema, - IReadOnlyList childCommandSchemas) - { - if (!childCommandSchemas.Any()) - return; - - // Margin - if (!_isEmpty) - RenderNewLine(); - - // Header - RenderHeader("Commands"); - - // Child commands - foreach (var childCommandSchema in childCommandSchemas) - { - var relativeCommandName = GetRelativeCommandName(childCommandSchema, commandSchema); - - // Name - RenderIndent(); - Render(relativeCommandName, ConsoleColor.Cyan); - - // Description - if (!childCommandSchema.Description.IsNullOrWhiteSpace()) - { - RenderColumnIndent(); - Render(childCommandSchema.Description); - } - - RenderNewLine(); - } - - // Margin - RenderNewLine(); - - // Child command help tip - Render("You can run `"); - Render(applicationMetadata.ExecutableName); - - if (!commandSchema.IsDefault()) - { Render(" "); - Render(commandSchema.Name, ConsoleColor.Cyan); + Render("--help", ConsoleColor.White); + + Render("` to show help on a specific command."); + + RenderNewLine(); } - Render(" "); - Render("[command]", ConsoleColor.Cyan); - - Render(" "); - Render("--help", ConsoleColor.White); - - Render("` to show help on a specific command."); - - RenderNewLine(); - } - - public void RenderHelpText(ApplicationMetadata applicationMetadata, - IReadOnlyList availableCommandSchemas, CommandSchema matchingCommandSchema) - { - var childCommandSchemas = availableCommandSchemas - .Where(c => availableCommandSchemas.FindParent(c.Name) == matchingCommandSchema) - .ToArray(); - - RenderApplicationInfo(applicationMetadata, matchingCommandSchema); - RenderDescription(matchingCommandSchema); - RenderUsage(applicationMetadata, matchingCommandSchema, childCommandSchemas); - RenderOptions(matchingCommandSchema); - RenderChildCommands(applicationMetadata, matchingCommandSchema, childCommandSchemas); + public void RenderHelpText() + { + RenderApplicationInfo(); + RenderDescription(); + RenderUsage(); + RenderOptions(); + RenderChildCommands(); + } } } public partial class CommandHelpTextRenderer { + private static IEnumerable GetChildCommandSchemas(IReadOnlyList availableCommandSchemas, + CommandSchema parentCommandSchema) => + availableCommandSchemas.Where(c => availableCommandSchemas.FindParent(c.Name) == parentCommandSchema); + private static string GetRelativeCommandName(CommandSchema commandSchema, CommandSchema parentCommandSchema) => parentCommandSchema.Name.IsNullOrWhiteSpace() ? commandSchema.Name diff --git a/CliFx/Services/ICommandHelpTextRenderer.cs b/CliFx/Services/ICommandHelpTextRenderer.cs index 305451d..b7f67df 100644 --- a/CliFx/Services/ICommandHelpTextRenderer.cs +++ b/CliFx/Services/ICommandHelpTextRenderer.cs @@ -1,11 +1,9 @@ -using System.Collections.Generic; -using CliFx.Models; +using CliFx.Models; namespace CliFx.Services { public interface ICommandHelpTextRenderer { - void RenderHelpText(ApplicationMetadata applicationMetadata, - IReadOnlyList availableCommandSchemas, CommandSchema matchingCommandSchema); + void RenderHelpText(IConsole console, HelpTextSource source); } } \ No newline at end of file