Change ICommandHelpTextRenderer

This commit is contained in:
Alexey Golub
2019-08-13 18:00:26 +03:00
parent f09caa876f
commit a322632e46
5 changed files with 258 additions and 225 deletions

View File

@@ -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;
}

View File

@@ -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());
}
}
}

View File

@@ -0,0 +1,22 @@
using System.Collections.Generic;
namespace CliFx.Models
{
public class HelpTextSource
{
public ApplicationMetadata ApplicationMetadata { get; }
public IReadOnlyList<CommandSchema> AvailableCommandSchemas { get; }
public CommandSchema TargetCommandSchema { get; }
public HelpTextSource(ApplicationMetadata applicationMetadata,
IReadOnlyList<CommandSchema> availableCommandSchemas,
CommandSchema targetCommandSchema)
{
ApplicationMetadata = applicationMetadata;
AvailableCommandSchemas = availableCommandSchemas;
TargetCommandSchema = targetCommandSchema;
}
}
}

View File

@@ -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<CommandSchema> 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<CommandOptionSchema>();
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<CommandOptionSchema>();
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<CommandSchema> 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<CommandSchema> 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<CommandSchema> GetChildCommandSchemas(IReadOnlyList<CommandSchema> availableCommandSchemas,
CommandSchema parentCommandSchema) =>
availableCommandSchemas.Where(c => availableCommandSchemas.FindParent(c.Name) == parentCommandSchema);
private static string GetRelativeCommandName(CommandSchema commandSchema, CommandSchema parentCommandSchema) =>
parentCommandSchema.Name.IsNullOrWhiteSpace()
? commandSchema.Name

View File

@@ -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<CommandSchema> availableCommandSchemas, CommandSchema matchingCommandSchema);
void RenderHelpText(IConsole console, HelpTextSource source);
}
}