// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Runtime.CompilerServices;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;
using System.Text;
using System.Threading;
using Tools.DotNETCommon.XmlHandler;
using System.ComponentModel;
using System.Reflection;
namespace AutomationTool
{
#region Help
///
/// Help Attribute.
///
[AttributeUsage(AttributeTargets.All, AllowMultiple = true)]
public class HelpAttribute : DescriptionAttribute
{
private bool IsParamHelp;
///
/// Basic constructor for class descriptions.
///
/// Class description
public HelpAttribute(string Description)
: base(Description)
{
IsParamHelp = false;
}
///
/// Constructor for parameter descriptions.
///
/// Paramter name
/// Paramter description
public HelpAttribute(string ParamName, string Description)
: base(FormatDescription(ParamName, Description))
{
IsParamHelp = true;
}
///
/// Additional type to display help for.
///
///
public HelpAttribute(Type AdditionalType)
{
IsParamHelp = false;
AdditionalHelp = AdditionalType;
}
private static string FormatDescription(string Name, string Description)
{
return String.Format("-{0} {1}", Name, Description);
}
public bool IsParam
{
get { return IsParamHelp; }
}
public Type AdditionalHelp
{
get;
private set;
}
}
#endregion
///
/// Base utility function for script commands.
///
public partial class CommandUtils
{
#region Help
///
/// Displays help for the specified command.
/// Command type.
///
public static void Help(Type Command)
{
string Description;
List Params;
GetTypeHelp(Command, out Description, out Params);
LogHelp(Command, Description, Params);
}
///
/// Displays help for the specified Type.
///
/// Type to display help for.
public static void LogHelp(Type Command)
{
string Description;
List Params;
GetTypeHelp(Command, out Description, out Params);
LogHelp(Command, Description, Params);
}
///
/// Displays a formatted help for the specified Command type.
///
/// Command Type
/// Command Desscription
/// Command Parameters
public static void LogHelp(Type Command, string Description, List Params)
{
string HelpMessage = Environment.NewLine;
bool bFirstLine = true;
if (Command != null)
{
HelpMessage += String.Format("{0} Help:{1}", Command.Name, Environment.NewLine);
bFirstLine = false;
}
if (String.IsNullOrEmpty(Description) == false)
{
if (!bFirstLine)
{
HelpMessage += Environment.NewLine;
}
HelpMessage += Description + Environment.NewLine;
bFirstLine = false;
}
if (IsNullOrEmpty(Params) == false)
{
if (!bFirstLine)
{
HelpMessage += Environment.NewLine;
}
HelpMessage += "Parameters: " + Environment.NewLine;
HelpMessage += Environment.NewLine;
HelpMessage += FormatParams(Params, 4, 24);
}
Log(HelpMessage);
}
///
/// 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)
///
static string FormatParams(List Params, int Indent, int DefaultRightPadding)
{
Dictionary ParamDict = new Dictionary(StringComparer.InvariantCultureIgnoreCase);
// Extract Params/Descriptions into Key/Value pairs
foreach (var Param in Params)
{
// Find the first space (should be following the param name)
if (!String.IsNullOrWhiteSpace(Param))
{
var ParamName = String.Empty;
var ParamDesc = String.Empty;
var SplitPoint = Param.IndexOf(' ');
if (SplitPoint > 0)
{
// Extract the name and description seperately
ParamName = Param.Substring(0, SplitPoint);
ParamDesc = Param.Substring(SplitPoint + 1, Param.Length - (SplitPoint + 1));
}
else
{
ParamName = Param;
}
// build dictionary using Name and Desc as Key and Value
if (!ParamDict.ContainsKey(ParamName))
{
ParamDict.Add(ParamName, ParamDesc);
}
else
{
LogWarning("Duplicated help parameter \"{0}\"", ParamName);
}
}
}
// string used to intent the param
string IndentString = string.Empty.PadRight(Indent);
// default the padding value
int RightPadding = DefaultRightPadding;
// If (Padding < longest param name) padding = longest param name + 1
foreach (var ParamName in ParamDict.Keys)
{
if (ParamName.Length + 1 > RightPadding)
{
RightPadding = ParamName.Length + 1;
}
}
// results string
string FormattedParams = string.Empty;
// Build the formatted params
foreach (var ParamName in ParamDict.Keys)
{
// build the param first, including intend and padding on the rights size
string ParamString = IndentString + ParamName.PadRight(RightPadding);
// Build the description line by line, adding the same amount of intending each time.
foreach (var DescriptionLine in WordWrap(ParamDict[ParamName], Console.WindowWidth - ParamString.Length))
{
// Formatting as following:
// -paramDescription
FormattedParams += ParamString + DescriptionLine + Environment.NewLine;
// we replace the param string on subsequent lines with white space of the same length
ParamString = string.Empty.PadRight(IndentString.Length + RightPadding);
}
// new line after each param/desc combo
FormattedParams += Environment.NewLine;
}
return FormattedParams;
}
///
/// Takes a given sentence and wraps it on a word by word basis so that no line exceeds the
/// set maximum line length. Words longer than a line are broken up. Returns the sentence as
/// a list of individual lines.
///
/// The sentence to be wrapped
/// The maximum (non negative) length of the returned sentences
/// The provided sentence in a list of individual lines no longer than MaximumLineLength
static List WordWrap(string Sentence, int MaximumLineLength)
{
// Early out
if (Sentence.Length == 0)
{
return new List();
}
string[] words = Sentence.Split(' ');
List WrappedWords = new List();
string CurrentSentence = string.Empty;
foreach (var word in words)
{
// if this is a very large word, split it
if (word.Length > MaximumLineLength)
{
// Top up the current line
WrappedWords.Add(CurrentSentence + word.Substring(0, MaximumLineLength - CurrentSentence.Length));
int length = MaximumLineLength - CurrentSentence.Length;
while (length + MaximumLineLength < word.Length)
{
// Place the starting lengths into their own lines
WrappedWords.Add(word.Substring(length, Math.Min(MaximumLineLength, word.Length - length)));
length += MaximumLineLength;
}
// then the trailing end into the next line
CurrentSentence += word.Substring(length, Math.Min(MaximumLineLength, word.Length - length)) + " ";
}
else
{
if (CurrentSentence.Length + word.Length > MaximumLineLength)
{
// next line and reset sentence
WrappedWords.Add(CurrentSentence);
CurrentSentence = string.Empty;
}
// Add the word to the current sentence.
CurrentSentence += word + " ";
}
}
if (CurrentSentence.Length > 0)
{
WrappedWords.Add(CurrentSentence);
}
return WrappedWords;
}
///
/// Gets the description and a list of parameters for the specified type.
///
/// Type to get help for.
/// Description
/// List of paramters
public static void GetTypeHelp(Type ObjType, out string ObjectDescription, out List Params)
{
ObjectDescription = String.Empty;
Params = new List();
var AllAttributes = ObjType.GetCustomAttributes(false);
foreach (var CustomAttribute in AllAttributes)
{
var HelpAttribute = CustomAttribute as HelpAttribute;
if (HelpAttribute != null)
{
if (HelpAttribute.IsParam)
{
Params.Add(HelpAttribute.Description);
}
else if (HelpAttribute.AdditionalHelp != null)
{
string DummyDescription;
List AdditionalParams;
GetTypeHelp(HelpAttribute.AdditionalHelp, out DummyDescription, out AdditionalParams);
Params.AddRange(AdditionalParams);
}
else
{
ObjectDescription = HelpAttribute.Description;
}
}
}
var AllMembers = GetAllMemebers(ObjType);
foreach (var Member in AllMembers)
{
var AllMemeberAtributes = Member.GetCustomAttributes(false);
foreach (var CustomAttribute in AllMemeberAtributes)
{
var HelpAttribute = CustomAttribute as HelpAttribute;
if (HelpAttribute != null && HelpAttribute.IsParam)
{
Params.Add(HelpAttribute.Description);
}
}
}
}
private static List GetAllMemebers(Type ObjType)
{
var Members = new List();
for (; ObjType != null; ObjType = ObjType.BaseType)
{
var ObjMembers = ObjType.GetMembers(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static);
Members.AddRange(ObjMembers);
}
return Members;
}
#endregion
}
}