mirror of
https://github.com/Tyrrrz/CliFx.git
synced 2025-10-25 15:19:17 +00:00
Render help text properly in two columns
This commit is contained in:
@@ -10,7 +10,9 @@ namespace CliFx.Internal
|
|||||||
{
|
{
|
||||||
public static bool IsNullOrWhiteSpace(this string s) => string.IsNullOrWhiteSpace(s);
|
public static bool IsNullOrWhiteSpace(this string s) => string.IsNullOrWhiteSpace(s);
|
||||||
|
|
||||||
public static string AsString(this char c) => new string(c, 1);
|
public static string Repeat(this char c, int count) => new string(c, count);
|
||||||
|
|
||||||
|
public static string AsString(this char c) => c.Repeat(1);
|
||||||
|
|
||||||
public static string JoinToString<T>(this IEnumerable<T> source, string separator) => string.Join(separator, source);
|
public static string JoinToString<T>(this IEnumerable<T> source, string separator) => string.Join(separator, source);
|
||||||
|
|
||||||
|
|||||||
@@ -10,55 +10,80 @@ namespace CliFx.Services
|
|||||||
{
|
{
|
||||||
private readonly IConsole _console;
|
private readonly IConsole _console;
|
||||||
|
|
||||||
|
private int _position;
|
||||||
|
|
||||||
public CommandHelpTextRenderer(IConsole console)
|
public CommandHelpTextRenderer(IConsole console)
|
||||||
{
|
{
|
||||||
_console = console;
|
_console = console;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void Render(string text)
|
||||||
|
{
|
||||||
|
_console.Output.Write(text);
|
||||||
|
_position += text.Length;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RenderNewLine()
|
||||||
|
{
|
||||||
|
_console.Output.WriteLine();
|
||||||
|
_position = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RenderIndent(int depth = 2) => Render(' '.Repeat(depth));
|
||||||
|
|
||||||
|
private void Render(string text, ConsoleColor foregroundColor, ConsoleColor backgroundColor = ConsoleColor.Black) =>
|
||||||
|
_console.WithColor(foregroundColor, backgroundColor, c => Render(text));
|
||||||
|
|
||||||
private void RenderDescription(CommandSchema commandSchema)
|
private void RenderDescription(CommandSchema commandSchema)
|
||||||
{
|
{
|
||||||
if (commandSchema.Description.IsNullOrWhiteSpace())
|
if (commandSchema.Description.IsNullOrWhiteSpace())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_console.WithColor(ConsoleColor.Black, ConsoleColor.DarkGray, c =>
|
// Header
|
||||||
{
|
Render("Description", ConsoleColor.Black, ConsoleColor.DarkGray);
|
||||||
c.Output.WriteLine("Description");
|
RenderNewLine();
|
||||||
});
|
|
||||||
|
|
||||||
_console.Output.Write(" ");
|
// Description
|
||||||
_console.Output.Write(commandSchema.Description);
|
RenderIndent();
|
||||||
_console.Output.WriteLine();
|
Render(commandSchema.Description);
|
||||||
|
RenderNewLine();
|
||||||
|
|
||||||
_console.Output.WriteLine();
|
// Margin
|
||||||
|
RenderNewLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RenderUsage(ApplicationMetadata applicationMetadata, CommandSchema commandSchema, bool hasChildCommands)
|
private void RenderUsage(ApplicationMetadata applicationMetadata, CommandSchema commandSchema,
|
||||||
|
IReadOnlyList<CommandSchema> childCommandSchemas)
|
||||||
{
|
{
|
||||||
_console.WithColor(ConsoleColor.Black, ConsoleColor.DarkGray, c =>
|
// Header
|
||||||
{
|
Render("Usage", ConsoleColor.Black, ConsoleColor.DarkGray);
|
||||||
c.Output.WriteLine("Usage");
|
RenderNewLine();
|
||||||
});
|
|
||||||
|
|
||||||
_console.Output.Write(" ");
|
// Exe name
|
||||||
|
RenderIndent();
|
||||||
_console.Output.Write(applicationMetadata.ExecutableName);
|
Render(applicationMetadata.ExecutableName);
|
||||||
_console.Output.Write(' ');
|
|
||||||
|
|
||||||
|
// Command name
|
||||||
if (!commandSchema.IsDefault())
|
if (!commandSchema.IsDefault())
|
||||||
{
|
{
|
||||||
_console.Output.Write(commandSchema.Name);
|
Render(" ");
|
||||||
_console.Output.Write(' ');
|
Render(commandSchema.Name, ConsoleColor.Cyan);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasChildCommands)
|
// Child command
|
||||||
|
if (childCommandSchemas.Any())
|
||||||
{
|
{
|
||||||
_console.Output.Write("[command]");
|
Render(" ");
|
||||||
_console.Output.Write(' ');
|
Render("[command]", ConsoleColor.Cyan);
|
||||||
}
|
}
|
||||||
|
|
||||||
_console.Output.Write("[options]");
|
// Options
|
||||||
_console.Output.WriteLine();
|
Render(" ");
|
||||||
_console.Output.WriteLine();
|
Render("[options]", ConsoleColor.White);
|
||||||
|
RenderNewLine();
|
||||||
|
|
||||||
|
// Margin
|
||||||
|
RenderNewLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RenderOptions(CommandSchema commandSchema)
|
private void RenderOptions(CommandSchema commandSchema)
|
||||||
@@ -69,50 +94,57 @@ namespace CliFx.Services
|
|||||||
options.Add(new CommandOptionSchema(null, "help", 'h', null, false, "Shows help text."));
|
options.Add(new CommandOptionSchema(null, "help", 'h', null, false, "Shows help text."));
|
||||||
|
|
||||||
if (commandSchema.IsDefault())
|
if (commandSchema.IsDefault())
|
||||||
options.Add(new CommandOptionSchema(null, "version", 'v', null, false, "Shows application version."));
|
options.Add(new CommandOptionSchema(null, "version", null, null, false, "Shows application version."));
|
||||||
|
|
||||||
_console.WithColor(ConsoleColor.Black, ConsoleColor.DarkGray, c =>
|
// Header
|
||||||
{
|
Render("Options", ConsoleColor.Black, ConsoleColor.DarkGray);
|
||||||
c.Output.WriteLine("Options");
|
RenderNewLine();
|
||||||
});
|
|
||||||
|
|
||||||
|
// Options
|
||||||
foreach (var option in options)
|
foreach (var option in options)
|
||||||
{
|
{
|
||||||
_console.Output.Write(" ");
|
RenderIndent();
|
||||||
|
|
||||||
if (!option.Name.IsNullOrWhiteSpace())
|
|
||||||
{
|
|
||||||
_console.WithColor(option.IsRequired ? ConsoleColor.White : ConsoleColor.Gray, c =>
|
|
||||||
{
|
|
||||||
c.Output.Write("--");
|
|
||||||
c.Output.Write(option.Name);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!option.Name.IsNullOrWhiteSpace() && option.ShortName != null)
|
|
||||||
{
|
|
||||||
_console.Output.Write('|');
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// Short name
|
||||||
if (option.ShortName != null)
|
if (option.ShortName != null)
|
||||||
{
|
{
|
||||||
_console.WithColor(option.IsRequired ? ConsoleColor.White: ConsoleColor.Gray, c =>
|
Render($"-{option.ShortName}", ConsoleColor.White);
|
||||||
{
|
|
||||||
c.Output.Write('-');
|
|
||||||
c.Output.Write(option.ShortName);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Delimiter
|
||||||
|
if (!option.Name.IsNullOrWhiteSpace() && option.ShortName != null)
|
||||||
|
{
|
||||||
|
Render("|");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Name
|
||||||
|
if (!option.Name.IsNullOrWhiteSpace())
|
||||||
|
{
|
||||||
|
Render($"--{option.Name}", ConsoleColor.White);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Description
|
||||||
if (!option.Description.IsNullOrWhiteSpace())
|
if (!option.Description.IsNullOrWhiteSpace())
|
||||||
{
|
{
|
||||||
_console.Output.Write(" ");
|
const int threshold = 20;
|
||||||
_console.Output.Write(option.Description);
|
|
||||||
|
if (_position >= threshold)
|
||||||
|
{
|
||||||
|
RenderNewLine();
|
||||||
|
RenderIndent(threshold);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
RenderIndent(threshold - _position);
|
||||||
|
}
|
||||||
|
|
||||||
|
Render(option.Description);
|
||||||
}
|
}
|
||||||
|
|
||||||
_console.Output.WriteLine();
|
RenderNewLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
_console.Output.WriteLine();
|
RenderNewLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RenderChildCommands(ApplicationMetadata applicationMetadata, CommandSchema commandSchema,
|
private void RenderChildCommands(ApplicationMetadata applicationMetadata, CommandSchema commandSchema,
|
||||||
@@ -121,44 +153,62 @@ namespace CliFx.Services
|
|||||||
if (!childCommandSchemas.Any())
|
if (!childCommandSchemas.Any())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_console.WithColor(ConsoleColor.Black, ConsoleColor.DarkGray, c =>
|
// Header
|
||||||
{
|
Render("Commands", ConsoleColor.Black, ConsoleColor.DarkGray);
|
||||||
c.Output.WriteLine("Commands");
|
RenderNewLine();
|
||||||
});
|
|
||||||
|
|
||||||
|
// Child commands
|
||||||
foreach (var childCommandSchema in childCommandSchemas)
|
foreach (var childCommandSchema in childCommandSchemas)
|
||||||
{
|
{
|
||||||
_console.Output.Write(" ");
|
var relativeCommandName = GetRelativeCommandName(childCommandSchema, commandSchema);
|
||||||
|
|
||||||
_console.Output.Write(GetRelativeCommandName(childCommandSchema, commandSchema));
|
// Name
|
||||||
|
RenderIndent();
|
||||||
|
Render(relativeCommandName, ConsoleColor.Cyan);
|
||||||
|
|
||||||
|
// Description
|
||||||
if (!childCommandSchema.Description.IsNullOrWhiteSpace())
|
if (!childCommandSchema.Description.IsNullOrWhiteSpace())
|
||||||
{
|
{
|
||||||
_console.Output.Write(" ");
|
const int threshold = 20;
|
||||||
_console.Output.Write(childCommandSchema.Description);
|
|
||||||
|
if (_position >= threshold)
|
||||||
|
{
|
||||||
|
RenderNewLine();
|
||||||
|
RenderIndent(threshold);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
RenderIndent(threshold - _position);
|
||||||
|
}
|
||||||
|
|
||||||
|
Render(childCommandSchema.Description);
|
||||||
}
|
}
|
||||||
|
|
||||||
_console.Output.WriteLine();
|
RenderNewLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
_console.Output.WriteLine();
|
// Margin
|
||||||
|
RenderNewLine();
|
||||||
|
|
||||||
// Child command help tip
|
// Child command help tip
|
||||||
|
Render("You can run `");
|
||||||
_console.Output.Write("You can run `");
|
Render(applicationMetadata.ExecutableName);
|
||||||
|
|
||||||
_console.Output.Write(applicationMetadata.ExecutableName);
|
|
||||||
_console.Output.Write(' ');
|
|
||||||
|
|
||||||
if (!commandSchema.IsDefault())
|
if (!commandSchema.IsDefault())
|
||||||
{
|
{
|
||||||
_console.Output.Write(commandSchema.Name);
|
Render(" ");
|
||||||
_console.Output.Write(' ');
|
Render(commandSchema.Name, ConsoleColor.Cyan);
|
||||||
}
|
}
|
||||||
|
|
||||||
_console.Output.Write("[command] --help` to show help on a specific command.");
|
Render(" ");
|
||||||
|
Render("[command]", ConsoleColor.Cyan);
|
||||||
|
|
||||||
_console.Output.WriteLine();
|
Render(" ");
|
||||||
|
Render("--help", ConsoleColor.White);
|
||||||
|
|
||||||
|
Render("` to show help on a specific command.");
|
||||||
|
|
||||||
|
RenderNewLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RenderHelpText(ApplicationMetadata applicationMetadata,
|
public void RenderHelpText(ApplicationMetadata applicationMetadata,
|
||||||
@@ -171,15 +221,13 @@ namespace CliFx.Services
|
|||||||
// Render application info
|
// Render application info
|
||||||
if (matchingCommandSchema.IsDefault())
|
if (matchingCommandSchema.IsDefault())
|
||||||
{
|
{
|
||||||
_console.Output.Write(applicationMetadata.Title);
|
Render($"{applicationMetadata.Title} v{applicationMetadata.VersionText}", ConsoleColor.Yellow);
|
||||||
_console.Output.Write(" v");
|
RenderNewLine();
|
||||||
_console.Output.Write(applicationMetadata.VersionText);
|
RenderNewLine();
|
||||||
_console.Output.WriteLine();
|
|
||||||
_console.Output.WriteLine();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RenderDescription(matchingCommandSchema);
|
RenderDescription(matchingCommandSchema);
|
||||||
RenderUsage(applicationMetadata, matchingCommandSchema, childCommandSchemas.Any());
|
RenderUsage(applicationMetadata, matchingCommandSchema, childCommandSchemas);
|
||||||
RenderOptions(matchingCommandSchema);
|
RenderOptions(matchingCommandSchema);
|
||||||
RenderChildCommands(applicationMetadata, matchingCommandSchema, childCommandSchemas);
|
RenderChildCommands(applicationMetadata, matchingCommandSchema, childCommandSchemas);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user