// 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 } }