// Copyright Epic Games, Inc. All Rights Reserved.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using Microsoft.Extensions.Logging;
namespace EpicGames.Core
{
///
/// Utility functions for showing help for objects
///
public static class HelpUtils
{
///
/// Gets the width of the window for formatting purposes
///
public static int WindowWidth => ConsoleUtils.WindowWidth;
///
/// Prints help for the given object type
///
///
/// Type to print help for
public static void PrintHelp(string title, Type type)
{
PrintHelp(title, GetDescription(type), CommandLineArguments.GetParameters(type));
}
///
/// Prints help for a command
///
/// Title for the help text
/// Description for the command
/// List of parameters
public static void PrintHelp(string? title, string? description, List> parameters)
{
bool bFirstLine = true;
if (!String.IsNullOrEmpty(title))
{
PrintParagraph(title);
bFirstLine = false;
}
if (!String.IsNullOrEmpty(description))
{
if (!bFirstLine)
{
Console.WriteLine("");
}
PrintParagraph(description);
bFirstLine = false;
}
if (parameters.Count > 0)
{
if (!bFirstLine)
{
Console.WriteLine("");
}
Console.WriteLine("Parameters:");
PrintTable(parameters, 4, 24);
}
}
///
/// Gets the description from a type
///
/// The type to get a description for
/// The description text
public static string GetDescription(Type type)
{
StringBuilder descriptionText = new StringBuilder();
foreach (DescriptionAttribute attribute in type.GetCustomAttributes(typeof(DescriptionAttribute), false).OfType())
{
if (descriptionText.Length > 0)
{
descriptionText.AppendLine();
}
descriptionText.AppendLine(attribute.Description);
}
return descriptionText.ToString();
}
///
/// Prints a paragraph of text using word wrapping
///
/// Text to print
public static void PrintParagraph(string text)
{
PrintParagraph(text, WindowWidth - 1);
}
///
/// Prints a paragraph of text using word wrapping
///
/// Text to print
/// Maximum width for each line
public static void PrintParagraph(string text, int maxWidth)
{
IEnumerable lines = StringUtils.WordWrap(text, maxWidth);
foreach (string line in lines)
{
Console.WriteLine(line);
}
}
///
/// Prints an argument list to the console
///
/// List of parameters arranged as "-ParamName Param Description"
/// Indent from the left hand side
/// The minimum padding from the start of the param name to the start of the description (resizes with larger param names)
///
public static void PrintTable(List> items, int indent, int minFirstColumnWidth)
{
List lines = [];
FormatTable(items, indent, minFirstColumnWidth, WindowWidth - 1, lines);
foreach (string line in lines)
{
Console.WriteLine(line);
}
}
///
/// Prints a table of items to a logging device
///
///
///
///
///
///
public static void PrintTable(List> items, int indent, int minFirstColumnWidth, int maxWidth, ILogger logger)
{
List lines = [];
FormatTable(items, indent, minFirstColumnWidth, maxWidth, lines);
foreach (string line in lines)
{
logger.LogInformation("{Line}", line);
}
}
///
/// Formats the given parameters as so:
/// -Param1 Param1 Description
///
/// -Param2 Param2 Description, this description is
/// longer and splits onto a separate line.
///
/// -Param3 Param3 Description continues as before.
///
/// List of parameters arranged as "-ParamName Param Description"
/// Indent from the left hand side
/// The minimum padding from the start of the param name to the start of the description (resizes with larger param names)
///
///
/// Sequence of formatted lines in the table
public static void FormatTable(IReadOnlyList> items, int indent, int minFirstColumnWidth, int maxWidth, List lines)
{
if(items.Count > 0)
{
// string used to intent the param
string indentString = new string(' ', indent);
// default the padding value
int rightPadding = Math.Max(minFirstColumnWidth, items.Max(x => x.Key.Length + 2));
// Build the formatted params
foreach(KeyValuePair item in items)
{
// build the param first, including intend and padding on the rights size
string paramString = indentString + item.Key.PadRight(rightPadding);
// Build the description line by line, adding the same amount of intending each time.
IEnumerable descriptionLines = StringUtils.WordWrap(item.Value, maxWidth - paramString.Length);
foreach(string descriptionLine in descriptionLines)
{
// Formatting as following:
// -paramDescription
lines.Add(paramString + descriptionLine);
// we replace the param string on subsequent lines with white space of the same length
paramString = String.Empty.PadRight(indentString.Length + rightPadding);
}
}
}
}
}
}