From 58c4d4683a2c09fbe0e16fe989e958d76f9c46f0 Mon Sep 17 00:00:00 2001 From: Matt Nadareski Date: Thu, 2 Feb 2017 13:22:06 -0800 Subject: [PATCH] [Help] Create recursive help system, not hooked up and not fully set up for SabreTools --- SabreTools.Helper/Data/Enums.cs | 14 + SabreTools.Helper/Help/Feature.cs | 366 +++++++++++ SabreTools.Helper/Help/Help.cs | 205 +++++++ SabreTools.Helper/SabreTools.Helper.csproj | 2 + SabreTools/Partials/SabreTools.Help.cs | 678 +++++++++++++++++++++ SabreTools/SabreTools.cs | 5 + SabreTools/SabreTools.csproj | 1 + 7 files changed, 1271 insertions(+) create mode 100644 SabreTools.Helper/Help/Feature.cs create mode 100644 SabreTools.Helper/Help/Help.cs create mode 100644 SabreTools/Partials/SabreTools.Help.cs diff --git a/SabreTools.Helper/Data/Enums.cs b/SabreTools.Helper/Data/Enums.cs index fcd1a5ca..411faf7b 100644 --- a/SabreTools.Helper/Data/Enums.cs +++ b/SabreTools.Helper/Data/Enums.cs @@ -285,6 +285,20 @@ #endregion + #region Help related + + /// + /// Determines the feature type to check for + /// + public enum FeatureType + { + Flag = 0, + String, + List, + } + + #endregion + #region Skippers and Mappers /// diff --git a/SabreTools.Helper/Help/Feature.cs b/SabreTools.Helper/Help/Feature.cs new file mode 100644 index 00000000..e6b9d90d --- /dev/null +++ b/SabreTools.Helper/Help/Feature.cs @@ -0,0 +1,366 @@ +using System; +using System.Collections.Generic; + +using SabreTools.Helper.Data; + +namespace SabreTools.Helper.Help +{ + public class Feature + { + #region Private variables + + private List _flags; + private string _description; + private FeatureType _featureType; + private Dictionary _features; + private List _additionalNotes; + private bool _foundOnce = false; + + #endregion + + #region Constructors + + public Feature() + { + _flags = new List(); + _description = null; + _featureType = FeatureType.Flag; + _features = new Dictionary(); + _additionalNotes = new List(); + } + + public Feature(string flag, string description, FeatureType featureType, List additionalNotes) + { + List flags = new List(); + flags.Add(flag); + _flags = flags; + _description = description; + _featureType = featureType; + _features = new Dictionary(); + _additionalNotes = additionalNotes; + } + + public Feature(List flags, string description, FeatureType featureType, List additionalNotes) + { + _flags = flags; + _description = description; + _featureType = featureType; + _features = new Dictionary(); + _additionalNotes = additionalNotes; + } + + #endregion + + #region Accessors + + /// + /// Directly address a given subfeature + /// + public Feature this[string name] + { + get { return _features[name]; } + set { _features[name] = value; } + } + + /// + /// Add a new feature for this feature + /// + /// Name of the feature to add + /// + public void AddFeature(string name, Feature feature) + { + if (_features == null) + { + _features = new Dictionary(); + } + + lock(_features) + { + if (!_features.ContainsKey(name)) + { + _features.Add(name, feature); + } + else + { + _features[name] = feature; + } + } + } + + /// + /// Add a new flag for this feature + /// + /// Flag to add for this feature + public void AddFlag(string flag) + { + if (_flags == null) + { + _flags = new List(); + } + + lock (_flags) + { + _flags.Add(flag); + } + } + + /// + /// Add a set of new flags for this feature + /// + /// List of flags to add to this feature + public void AddFlags(List flags) + { + if (_flags == null) + { + _flags = new List(); + } + + lock (_flags) + { + _flags.AddRange(flags); + } + } + + /// + /// Add a new additional note to this feature + /// + /// Note to add for this feature + public void AddNote(string note) + { + if (_additionalNotes == null) + { + _additionalNotes = new List(); + } + + lock (_additionalNotes) + { + _additionalNotes.Add(note); + } + } + + /// + /// Add a set of new notes for this feature + /// + /// List of notes to add to this feature + public void AddNotes(List notes) + { + if (_additionalNotes == null) + { + _additionalNotes = new List(); + } + + lock (_additionalNotes) + { + _additionalNotes.AddRange(notes); + } + } + + /// + /// Returns if a flag exists for the current feature + /// + /// Name of the flag to check + /// True if the flag was found, false otherwise + public bool ContainsFlag(string name) + { + bool success = false; + + // Loop through the flags + foreach (string flag in _flags) + { + if (flag == name) + { + success = true; + break; + } + else if (flag.TrimStart('-') == name) + { + success = true; + break; + } + } + + return success; + } + + /// + /// Returns if the feature contains a flag that starts with the given character + /// + /// Character to check against + /// True if the flag was found, false otherwise + public bool StartsWith(char c) + { + bool success = false; + + // Loop through the flags + foreach (string flag in _flags) + { + if (flag.TrimStart('-').ToLowerInvariant()[0] == c) + { + success = true; + break; + } + } + + return success; + } + + #endregion + + #region Instance Methods + + /// + /// Output this feature only + /// + /// Positive number representing number of spaces to put in front of the feature + /// Positive number representing the column where the description should start + public List Output(int pre = 0, int midpoint = 0) + { + // Create the output list + List outputList = new List(); + + // Build the output string first + string output = ""; + + // Add the pre-space first + for (int i = 0; i < pre; i++) + { + output += " "; + } + + // Now add all flags + output += String.Join(", ", _flags); + + // If we have a midpoint set, check to see if the string needs padding + if (midpoint > 0 && output.Length < midpoint) + { + while (output.Length < midpoint) + { + output += " "; + } + } + else + { + output += " "; + } + + // Append the description + output += _description; + + // Now append it to the list + outputList.Add(output); + + return outputList; + } + + /// + /// Output this feature and all subfeatures + /// + /// Level of indentation for this feature + /// Positive number representing number of spaces to put in front of the feature + /// Positive number representing the column where the description should start + public List OutputRecursive(int tabLevel, int pre = 0, int midpoint = 0) + { + // Create the output list + List outputList = new List(); + + // Build the output string first + string output = ""; + + // Normalize based on the tab level + int preAdjusted = pre; + int midpointAdjusted = midpoint; + if (tabLevel > 0) + { + preAdjusted += 4 * tabLevel; + midpointAdjusted += 4 * tabLevel; + } + + // Add the pre-space first + for (int i = 0; i < preAdjusted; i++) + { + output += " "; + } + + // Now add all flags + output += String.Join(", ", _flags); + + // If we have a midpoint set, check to see if the string needs padding + if (midpoint > 0 && output.Length < midpointAdjusted) + { + while (output.Length < midpointAdjusted) + { + output += " "; + } + } + else + { + output += " "; + } + + // Append the description + output += _description; + + // Now append it to the list + outputList.Add(output); + + // Now let's append all subfeatures + foreach (string feature in _features.Keys) + { + outputList.AddRange(_features[feature].OutputRecursive(tabLevel + 1, pre, midpoint)); + } + + return outputList; + } + + /// + /// Validate whether a flag is valid for this feature or not + /// + /// Input to check against + /// True if just this feature should be checked, false if all subfeatures are checked as well + /// True if the flag was valid, false otherwise + public bool ValidateInput(string input, bool exact = false) + { + bool valid = false; + + // Determine what we should be looking for + switch (_featureType) + { + // If we have a flag, make sure it doesn't have an equal sign in it + case FeatureType.Flag: + valid = !input.Contains("=") && _flags.Contains(input); + break; + + // If we have an input, make sure it has an equals sign in it + case FeatureType.List: + case FeatureType.String: + valid = input.Contains("=") && _flags.Contains(input.Split('=')[0]); + break; + } + + // If we haven't found a valid flag and we're not looking for just this feature, check to see if any of the subfeatures are valid + if (!valid && !exact) + { + foreach (string feature in _features.Keys) + { + valid = _features[feature].ValidateInput(input); + + // If we've found a valid feature, we break out + if (valid) + { + break; + } + } + } + + // If we've already found this flag before and we don't allow duplicates, set valid to false + if (valid && _foundOnce && _featureType != FeatureType.List) + { + valid = false; + } + + return valid; + } + + #endregion + } +} diff --git a/SabreTools.Helper/Help/Help.cs b/SabreTools.Helper/Help/Help.cs new file mode 100644 index 00000000..b7a9e01d --- /dev/null +++ b/SabreTools.Helper/Help/Help.cs @@ -0,0 +1,205 @@ +using System; +using System.Collections.Generic; + +namespace SabreTools.Helper.Help +{ + public class Help + { + #region Private variables + + private List _header; + private Dictionary _features; + + #endregion + + #region Constructors + + public Help() + { + _header = new List(); + _features = new Dictionary(); + } + + public Help(List header) + { + _header = header; + _features = new Dictionary(); + } + + #endregion + + #region Accessors + + /// + /// Add a new feature to the help + /// + /// Name of the feature to add + /// Feature object to map to + public void Add(string name, Feature feature) + { + if (_features == null) + { + _features = new Dictionary(); + } + + lock (_features) + { + _features.Add(name, feature); + } + } + + #endregion + + #region Instance Methods + + /// + /// Output top-level features only + /// + public void OutputGenericHelp() + { + // Start building the output list + List output = new List(); + + // Append the header first + output.AddRange(_header); + + // Now append all available top-level flags + output.Add("Available options:"); + foreach (string feature in _features.Keys) + { + output.AddRange(_features[feature].Output(pre: 2, midpoint: 25)); + } + + // And append the generic ending + output.Add(""); + output.Add("For information on available flags, put the option name after help"); + + // Now write out everything in a staged manner + WriteOutWithPauses(output); + } + + /// + /// Output all features recursively + /// + public void OutputAllHelp() + { + // Start building the output list + List output = new List(); + + // Append the header first + output.AddRange(_header); + + // Now append all available flags recursively + output.Add("Available options:"); + foreach (string feature in _features.Keys) + { + output.AddRange(_features[feature].OutputRecursive(0, pre: 2, midpoint: 25)); + } + + // Now write out everything in a staged manner + WriteOutWithPauses(output); + } + + /// + /// Output a single feature recursively + /// + public void OutputIndividualFeature(string featurename) + { + // Start building the output list + List output = new List(); + + // Append the header first + output.AddRange(_header); + + // Now try to find the feature that has the name included + string realname = null; + List startsWith = new List(); + foreach (string feature in _features.Keys) + { + // If we have a match to the feature name somehow + if (feature == featurename) + { + realname = feature; + break; + } + + // If we have a match within the flags + else if (_features[feature].ContainsFlag(featurename)) + { + realname = feature; + break; + } + + // Otherwise, we want to get features with the same start + else if (_features[feature].StartsWith(featurename[0])) + { + startsWith.Add(feature); + } + } + + // If we have a real name found, append all available subflags recursively + if (realname != null) + { + output.Add("Available options for " + realname + ":"); + output.AddRange(_features[realname].OutputRecursive(0, pre: 2, midpoint: 25)); + } + + // If no name was found but we have possible matches, show them + else if (startsWith.Count > 0) + { + output.Add(featurename + " not found. Did you mean:"); + foreach (string possible in startsWith) + { + output.AddRange(_features[possible].Output(pre: 2, midpoint: 25)); + } + } + + // Now write out everything in a staged manner + WriteOutWithPauses(output); + } + + /// + /// Write out the help text with pauses, if needed + /// + /// + private void WriteOutWithPauses(List helptext) + { + // Now output based on the size of the screen + int i = 0; + foreach (string help in helptext) + { + Console.WriteLine(help); + i++; + + // If we're not being redirected and we reached the size of the screen, pause + if (i == Console.WindowHeight - 3) + { + i = 0; + Pause(); + } + } + Pause(); + } + + /// + /// Pause on console output + /// + private static void Pause() + { + if (!Console.IsOutputRedirected) + { + Console.WriteLine(); + Console.WriteLine("Press enter to continue..."); + Console.ReadLine(); + } + } + + /* + * Here is a non-comprehensive list of things we want a help method to do: + * - Parse and return flags from arguments + * - Perform partial matching to find potentially similar features + */ + + #endregion + } +} diff --git a/SabreTools.Helper/SabreTools.Helper.csproj b/SabreTools.Helper/SabreTools.Helper.csproj index d62ad2ff..08236515 100644 --- a/SabreTools.Helper/SabreTools.Helper.csproj +++ b/SabreTools.Helper/SabreTools.Helper.csproj @@ -146,6 +146,8 @@ + + diff --git a/SabreTools/Partials/SabreTools.Help.cs b/SabreTools/Partials/SabreTools.Help.cs new file mode 100644 index 00000000..7f882881 --- /dev/null +++ b/SabreTools/Partials/SabreTools.Help.cs @@ -0,0 +1,678 @@ +using System.Collections.Generic; + +using SabreTools.Helper.Data; +using SabreTools.Helper.Help; +using SabreTools.Helper.Resources; + +namespace SabreTools +{ + public partial class SabreTools + { + public static Help RetrieveHelp() + { + // Create and add the header to the Help object + string barrier = "-----------------------------------------"; + List helpHeader = new List(); + helpHeader.Add(Resources.SabreTools_Name + " - " + Resources.SabreTools_Desc); + helpHeader.Add(barrier); + helpHeader.Add(Resources.Usage + ": " + Resources.SabreTools_Name + " [option] [flags] [filename|dirname] ..."); + helpHeader.Add(""); + Help help = new Help(helpHeader); + + // Create the Help feature + Feature helpFeature = new Feature( + new List() { "-?", "-h", "--help" }, + "Show this help", + FeatureType.Flag, + null); + + // Create the Script feature + Feature script = new Feature( + "--script", + "Enable script mode (no clear screen)", + FeatureType.Flag, + null); + + // Create the DATFromDir feature + Feature datFromDir = new Feature( + new List() { "-d", "--d2d", "--dfd" }, + "Create a DAT from an input directory", + FeatureType.Flag, + null); + datFromDir.AddFeature("noMD5", new Feature( + new List() { "-nm", "--noMD5" }, + "Don't include MD5 in output", + FeatureType.Flag, + null)); + datFromDir.AddFeature("noSHA1", new Feature( + new List() { "-ns", "--noSHA1" }, + "Don't include SHA1 in output", + FeatureType.Flag, + null)); + datFromDir.AddFeature("bare", new Feature( + new List() { "-b", "--bare" }, + "Don't include date in file name", + FeatureType.Flag, + null)); + datFromDir.AddFeature("forcepack", new Feature( + new List() { "-fp", "--forcepack" }, + "Set force packing", + FeatureType.String, + new List() + { + "Supported values are:", + " None, Zip, Unzip", + })); + datFromDir.AddFeature("files", new Feature( + new List() { "-f", "--files" }, + "Treat archives as files", + FeatureType.Flag, + null)); + datFromDir.AddFeature("output-all", new Feature( + new List() { "-oa", "--output-all" }, + "Output in all formats", + FeatureType.Flag, + null)); + datFromDir.AddFeature("output-am", new Feature( + new List() { "-oam", "--output-am" }, + "Output in AttractMode format", + FeatureType.Flag, + null)); + datFromDir.AddFeature("output-cmp", new Feature( + new List() { "-oc", "--output-cmp" }, + "Output in CMP format", + FeatureType.Flag, + null)); + datFromDir.AddFeature("output-csv", new Feature( + new List() { "-ocsv", "--output-csv" }, + "Output in CSV format", + FeatureType.Flag, + null)); + datFromDir.AddFeature("output-dc", new Feature( + new List() { "-od", "--output-dc" }, + "Output in DOSCenter format", + FeatureType.Flag, + null)); + datFromDir.AddFeature("output-miss", new Feature( + new List() { "-om", "--output-miss" }, + "Output in Missfile format", + FeatureType.Flag, + null)); + datFromDir.AddFeature("output-md5", new Feature( + new List() { "-oa", "--output-md5" }, + "Output in MD5 format", + FeatureType.Flag, + null)); + datFromDir.AddFeature("output-ol", new Feature( + new List() { "-ool", "--output-ol" }, + "Output in OfflineList format", + FeatureType.Flag, + null)); + datFromDir.AddFeature("output-rc", new Feature( + new List() { "-or", "--output-rc" }, + "Output in RomCenter format", + FeatureType.Flag, + null)); + datFromDir.AddFeature("output-sd", new Feature( + new List() { "-os", "--output-sd" }, + "Output in SabreDat format", + FeatureType.Flag, + null)); + datFromDir.AddFeature("output-sfv", new Feature( + new List() { "-osfv", "--output-sfv" }, + "Output in SFV format", + FeatureType.Flag, + null)); + datFromDir.AddFeature("output-sha1", new Feature( + new List() { "-osfv", "--output-sha1" }, + "Output in SHA-1 format", + FeatureType.Flag, + null)); + datFromDir.AddFeature("output-sl", new Feature( + new List() { "-osl", "--output-sl" }, + "Output in Softwarelist format", + FeatureType.Flag, + null)); + datFromDir.AddFeature("output-tsv", new Feature( + new List() { "-otsv", "--output-tsv" }, + "Output in TSV format", + FeatureType.Flag, + null)); + datFromDir.AddFeature("output-xml", new Feature( + new List() { "-ox", "--output-xml" }, + "Output in Logiqx XML format [default]", + FeatureType.Flag, + null)); + datFromDir.AddFeature("gz-files", new Feature( + new List() { "-gzf", "--gz-files" }, + "Allow reading of GZIP files as archives", + FeatureType.Flag, + null)); + datFromDir.AddFeature("romba", new Feature( + new List() { "-ro", "--romba" }, + "Read files from a Romba input", + FeatureType.Flag, + null)); + datFromDir.AddFeature("filename", new Feature( + new List() { "-f", "--filename" }, + "Set the external name of the DAT", + FeatureType.String, + null)); + datFromDir.AddFeature("name", new Feature( + new List() { "-n", "--name" }, + "Set the internal name of the DAT", + FeatureType.String, + null)); + datFromDir.AddFeature("desc", new Feature( + new List() { "-d", "--desc" }, + "Set the description of the DAT", + FeatureType.String, + null)); + datFromDir.AddFeature("cat", new Feature( + new List() { "-c", "--cat" }, + "Set the category of the DAT", + FeatureType.String, + null)); + datFromDir.AddFeature("version", new Feature( + new List() { "-v", "--version" }, + "Set the version of the DAT", + FeatureType.String, + null)); + datFromDir.AddFeature("author", new Feature( + new List() { "-au", "--author" }, + "Set the author of the DAT", + FeatureType.String, + null)); + datFromDir.AddFeature("superdat", new Feature( + new List() { "-sd", "--superdat" }, + "Enable SuperDAT creation", + FeatureType.Flag, + null)); + datFromDir.AddFeature("exclude-of", new Feature( + new List() { "-xof", "--exclude-of" }, + "Exclude romof, cloneof, sampleof tags", + FeatureType.Flag, + null)); + datFromDir.AddFeature("add-blank", new Feature( + new List() { "-ab", "--add-blank" }, + "Output blank files for folders", + FeatureType.Flag, + null)); + datFromDir.AddFeature("add-date", new Feature( + new List() { "-ad", "--add-date" }, + "Output dates for each file parsed", + FeatureType.Flag, + null)); + datFromDir.AddFeature("copy-files", new Feature( + new List() { "-cf", "--copy-files" }, + "Copy files to the temp directory before parsing", + FeatureType.Flag, + null)); + datFromDir.AddFeature("header", new Feature( + new List() { "-h", "--header" }, + "Set a header skipper to use, blank means all", + FeatureType.Flag, + null)); + datFromDir.AddFeature("temp", new Feature( + new List() { "-t", "--temp" }, + "Set the temporary directory to use", + FeatureType.String, + null)); + datFromDir.AddFeature("mt", new Feature( + new List() { "-mt", "--mt" }, + "Amount of threads to use (default 4, -1 unlimted)", + FeatureType.String, + null)); + + // Create the Extract feature + Feature extract = new Feature( + new List() { "-ex", "--extract" }, + "Extract and remove copier headers", + FeatureType.Flag, + null); + extract.AddFeature("out", new Feature( + new List() { "-out", "--out" }, + "Output directory", + FeatureType.String, + null)); + + // Create the Extension Split feature + Feature extSplit = new Feature( + new List() { "-es", "--ext-split" }, + "Split a DAT by two file extensions", + FeatureType.Flag, + null); + extSplit.AddFeature("exta", new Feature( + new List() { "-exta", "--exta" }, + "First extension (multiple allowed)", + FeatureType.List, + null)); + extSplit.AddFeature("extb", new Feature( + new List() { "-extb", "--extb" }, + "Second extension (multiple allowed)", + FeatureType.List, + null)); + extSplit.AddFeature("out", new Feature( + new List() { "-out", "--out" }, + "Output directory", + FeatureType.String, + null)); + + // Create the Hash Split feature + Feature hashSplit = new Feature( + new List() { "-hs", "--hash-split" }, + "Split a DAT or folder by best-available hashes", + FeatureType.Flag, + null); + hashSplit.AddFeature("out", new Feature( + new List() { "-out", "--out" }, + "Output directory", + FeatureType.String, + null)); + + // Create the Level Split feature + Feature levelSplit = new Feature( + new List() { "-ls", "--lvl-split" }, + "Split a SuperDAT or folder by internal path", + FeatureType.Flag, + null); + levelSplit.AddFeature("out", new Feature( + new List() { "-out", "--out" }, + "Output directory", + FeatureType.String, + null)); + levelSplit.AddFeature("short", new Feature( + new List() { "-s", "--short" }, + "Use short output names", + FeatureType.Flag, + null)); + levelSplit.AddFeature("base", new Feature( + new List() { "-ba", "--base" }, + "Use source DAT as base name for outputs", + FeatureType.Flag, + null)); + + // Create the Restore feature + Feature restore = new Feature( + new List() { "-re", "--restore" }, + "Restore header to file based on SHA-1", + FeatureType.Flag, + null); + restore.AddFeature("out", new Feature( + new List() { "-out", "--out" }, + "Output directory", + FeatureType.String, + null)); + + // Create the Sort feature + Feature sort = new Feature( + new List() { "-ss", "--sort" }, + "Sort inputs by a set of DATs", + FeatureType.Flag, + new List() + { + "Archive scanning levels:", + " 0 Hash archive and contents", + " 1 Only hash contents", + " 2 Only hash archive", + }); + sort.AddFeature("dat", new Feature( + new List() { "-dat", "--dat" }, + "Input DAT to rebuild against", + FeatureType.List, + null)); + sort.AddFeature("out", new Feature( + new List() { "-out", "--out" }, + "Output directory", + FeatureType.String, + null)); + sort.AddFeature("temp", new Feature( + new List() { "-temp", "--temp" }, + "Set the temporary directory to use", + FeatureType.String, + null)); + sort.AddFeature("delete", new Feature( + new List() { "-del", "--delete" }, + "Delete fully rebuilt input files", + FeatureType.Flag, + null)); + sort.AddFeature("inverse", new Feature( + new List() { "-in", "--inverse" }, + "Rebuild only files not in DAT", + FeatureType.Flag, + null)); + sort.AddFeature("quick", new Feature( + new List() { "-qs", "--quick" }, + "Enable quick scanning of archives", + FeatureType.Flag, + null)); + sort.AddFeature("add-date", new Feature( + new List() { "-ad", "--add-date" }, + "Add original dates from DAT, if possible", + FeatureType.Flag, + null)); + /* + sort.AddFeature("t7z", new Feature( + new List() { "-t7z", "--t7z" }, + "Enable Torrent7z output", + FeatureType.Flag, + null)); + */ + sort.AddFeature("tar", new Feature( + new List() { "-tar", "--tar" }, + "Enable TAR output", + FeatureType.Flag, + null)); + sort.AddFeature("tgz", new Feature( + new List() { "-tgz", "--tgz" }, + "Enable TorrentGZ output", + FeatureType.Flag, + null)); + sort["tgz"].AddFeature("romba", new Feature( + new List() { "-r", "--romba" }, + "Enable Romba depot dir output", + FeatureType.Flag, + null)); + /* + sort.AddFeature("tlrz", new Feature( + new List() { "-tlrz", "--tlrz" }, + "Enable TorrentLRZ output", + FeatureType.Flag, + null)); + */ + /* + sort.AddFeature("trar", new Feature( + new List() { "-trar", "--trar" }, + "Enable TorrentRAR output", + FeatureType.Flag, + null)); + */ + /* + sort.AddFeature("txz", new Feature( + new List() { "-txz", "--txz" }, + "Enable TorrentXZ output", + FeatureType.Flag, + null)); + */ + sort.AddFeature("tzip", new Feature( + new List() { "-tzip", "--tzip" }, + "Enable TorrentZip output", + FeatureType.Flag, + null)); + sort.AddFeature("header", new Feature( + new List() { "-h", "--header" }, + "Set a header skipper to use, blank means all", + FeatureType.String, + null)); + sort.AddFeature("7z", new Feature( + new List() { "-7z", "--7z" }, + "Set scanning level for 7z archives (default 1)", + FeatureType.String, + null)); + sort.AddFeature("gz", new Feature( + new List() { "-gz", "--gz" }, + "Set scanning level for GZip archives (default 2)", + FeatureType.String, + null)); + sort.AddFeature("rar", new Feature( + new List() { "-rar", "--rar" }, + "Set scanning level for RAR archives (default 2)", + FeatureType.String, + null)); + sort.AddFeature("zip", new Feature( + new List() { "-zip", "--zip" }, + "Set scanning level for ZIP archives (default 1)", + FeatureType.String, + null)); + sort.AddFeature("update-dat", new Feature( + new List() { "-ud", "--update-dat" }, + "Output updated DAT to output directory", + FeatureType.Flag, + null)); + sort.AddFeature("mt", new Feature( + new List() { "-mt", "--mt" }, + "Amount of threads to use (default 4, -1 unlimted)", + FeatureType.String, + null)); + + /* + + // Create the Sort Depot feature + Feature sortDepot = new Feature( + new List() { "-ssd", "--sort-depot" }, + "Sort romba depots by a set of DATs", + FeatureType.Flag, + null); + helptext.Add(" -dat= Input DAT to rebuild against"); + helptext.Add(" -out= Output directory"); + helptext.Add(" -t=, --temp= Set the temporary directory to use"); + helptext.Add(" -del, --delete Delete fully rebuilt input files"); + helptext.Add(" -in, --inverse Rebuild only files not in DAT"); + helptext.Add(" -ad, --add-date Add original dates from DAT, if possible"); + //helptext.Add(" -t7z Enable Torrent7z output"); + helptext.Add(" -tar Enable TAR output"); + helptext.Add(" -tgz Enable TorrentGZ output"); + helptext.Add(" -r, --romba Enable Romba depot dir output"); + //helptext.Add(" -tlrz Enable TorrentLRZ output"); + //helptext.Add(" -trar Enable TorrentRAR output"); + //helptext.Add(" -txz Enable TorrentXZ output"); + helptext.Add(" -tzip Enable TorrentZip output"); + helptext.Add(" -h=, --header= Set a header skipper to use, blank means all"); + helptext.Add(" -ud, --update-dat Output updated DAT to output directory"); + helptext.Add(" -mt={4} Amount of threads to use (-1 unlimted)"); + + // Create the Stats feature + Feature stats = new Feature( + new List() { "-st", "--stats" }, + "Get statistics on all input DATs", + FeatureType.Flag, + null); + helptext.Add(" -bc, --baddump-col Add baddump stats to output"); + helptext.Add(" -csv, --csv Output in Comma-Separated Value format"); + helptext.Add(" -f=, --filename= Set the filename for the output"); + helptext.Add(" -out= Output directory"); + helptext.Add(" -html, --html Output in HTML format"); + helptext.Add(" -nc, --nodump-col Add nodump stats to output"); + helptext.Add(" -si, --single Show individual statistics"); + helptext.Add(" -tsv, --tsv Output in Tab-Separated Value format"); + + // Create the Type Split feature + Feature typeSplit = new Feature( + new List() { "-ts", "--type-split" }, + "Split a DAT or folder by file types (rom/disk)", + FeatureType.Flag, + null); + elptext.Add(" -out= Output directory"); + + // Create the Update feature + Feature update = new Feature( + new List() { "-ud", "--update" }, + "Update a DAT file", + FeatureType.Flag, + null); + helptext.Add(" -oa, --output-all Output in all formats"); + helptext.Add(" -oam, --output-am Output in AttractMode format"); + helptext.Add(" -oc, --output-cmp Output in CMP format"); + helptext.Add(" -ocsv, --output-csv Output in CSV format"); + helptext.Add(" -pre=, --prefix= Set prefix for all lines"); + helptext.Add(" -post=, --postfix= Set postfix for all lines"); + helptext.Add(" -q, --quotes Put double-quotes around each item"); + helptext.Add(" -od, --output-dc Output in DOSCenter format"); + helptext.Add(" -om, --output-miss Output in Missfile format"); + helptext.Add(" -r, --roms Output roms to miss instead of sets"); + helptext.Add(" -gp, --game-prefix Add game name as a prefix"); + helptext.Add(" -pre=, --prefix= Set prefix for all lines"); + helptext.Add(" -post=, --postfix= Set postfix for all lines"); + helptext.Add(" -q, --quotes Put double-quotes around each item"); + helptext.Add(" -ae=, --add-ext= Add an extension to each item"); + helptext.Add(" -rep=, --rep-ext= Replace all extensions with specified"); + helptext.Add(" -rme, --rem-ext Remove all extensions from each item"); + helptext.Add(" -ro, --romba Output in Romba format (requires SHA-1)"); + helptext.Add(" -tsv, --tsv Output in Tab-Separated Value format"); + helptext.Add(" -csv, --csv Output in Comma-Separated Value format"); + helptext.Add(" -omd5, --output-md5 Output in MD5 format"); + helptext.Add(" -gp, --game-prefix Add game name as a prefix"); + helptext.Add(" -ool, --output-ol Output in OfflineList format"); + helptext.Add(" -or, --output-rc Output in RomCenter format"); + helptext.Add(" -os, --output-sd Output in SabreDAT format"); + helptext.Add(" -osfv, --ouput-sfv Output in SFV format"); + helptext.Add(" -gp, --game-prefix Add game name as a prefix"); + helptext.Add(" -osha1, --output-sha1 Output in SHA-1 format"); + helptext.Add(" -gp, --game-prefix Add game name as a prefix"); + helptext.Add(" -osl, --output-sl Output in Softwarelist format"); + helptext.Add(" -otsv, --output-tsv Output in TSV format"); + helptext.Add(" -pre=, --prefix= Set prefix for all lines"); + helptext.Add(" -post=, --postfix= Set postfix for all lines"); + helptext.Add(" -q, --quotes Put double-quotes around each item"); + helptext.Add(" -ox, --output-xml Output in Logiqx XML format"); + helptext.Add(" -f=, --filename= Set a new filename"); + helptext.Add(" -n=, --name= Set a new internal name"); + helptext.Add(" -de=, --desc= Set a new description"); + helptext.Add(" -r=, --root= Set a new rootdir"); + helptext.Add(" -ca=, --category= Set a new category"); + helptext.Add(" -v=, --version= Set a new version"); + helptext.Add(" -da=, --date= Set a new date"); + helptext.Add(" -au=, --author= Set a new author"); + helptext.Add(" -em=, --email= Set a new email"); + helptext.Add(" -hp=, --homepage= Set a new homepage"); + helptext.Add(" -u=, --url= Set a new URL"); + helptext.Add(" -co=, --comment= Set a new comment"); + helptext.Add(" -h=, --header= Set a new header skipper"); + helptext.Add(" -sd=, --superdat Set SuperDAT type"); + helptext.Add(" -fm=, --forcemerge= Set force merging"); + helptext.Add(" Supported values are:"); + helptext.Add(" None, Split, Full"); + helptext.Add(" -fn=, --forcend= Set force nodump"); + helptext.Add(" Supported values are:"); + helptext.Add(" None, Obsolete, Required, Ignore"); + helptext.Add(" -fp=, --forcepack= Set force packing"); + helptext.Add(" Supported values are:"); + helptext.Add(" None, Zip, Unzip"); + helptext.Add(" -xof, --exclude-of Exclude romof, cloneof, sampleof tags"); + helptext.Add(" -clean Clean game names according to WoD standards"); + helptext.Add(" -sl, --softlist Use Software List name instead of description"); + helptext.Add(" -dm, --dat-merged Create merged sets"); + helptext.Add(" -ds, --dat-split Create split sets"); + helptext.Add(" -dnm, --dat-nonmerged Create non-merged sets"); + helptext.Add(" -df, --dat-fullnonmerged Create fully non-merged sets"); + helptext.Add(" -trim Trim file names to fit NTFS length"); + helptext.Add(" -rd=, --root-dir= Set the root directory for calc"); + helptext.Add(" -si, --single All game names replaced by '!'"); + helptext.Add(" -dd, --dedup Enable deduping in the created DAT"); + helptext.Add(" -m, --merge Merge the input DATs"); + helptext.Add(" -b, --bare Don't include date in automatic name"); + helptext.Add(" -di, --diff Create diffdats from inputs (all outputs)"); + helptext.Add(" -b, --bare Don't include date in automatic name"); + helptext.Add(" -c, --cascade Enable cascaded diffing"); + helptext.Add(" -ip, --inplace Enable inplace, cascaded diff"); + helptext.Add(" -sf, --skip Skip output of first DAT"); + helptext.Add(" -rc, --rev-cascade Enable reverse cascaded diffing"); + helptext.Add(" -ip, --inplace Enable inplace, cascaded diff"); + helptext.Add(" -sf, --skip Skip output of first DAT"); + helptext.Add(" -did, --diff-du Create diffdat containing just duplicates"); + helptext.Add(" -b, --bare Don't include date in automatic name"); + helptext.Add(" -dii, --diff-in Create diffdats for individual DATs"); + helptext.Add(" -b, --bare Don't include date in automatic name"); + helptext.Add(" -din, --diff-nd Create diffdat containing no duplicates"); + helptext.Add(" -b, --bare Don't include date in automatic name"); + helptext.Add(" -gn=, --game-name= Filter by game name"); + helptext.Add(" -ngn=, --not-game= Filter by not game name"); + helptext.Add(" -rn=, --rom-name= Filter by rom name"); + helptext.Add(" -nrn=, --not-rom= Filter by not rom name"); + helptext.Add(" -rt=, --rom-type= Filter by rom type"); + helptext.Add(" -nrt=, --not-type= Filter by not rom type"); + helptext.Add(" -sgt=, --greater= Filter by size >="); + helptext.Add(" -slt=, --less= Filter by size <="); + helptext.Add(" -seq=, --equal= Filter by size =="); + helptext.Add(" -crc=, --crc= Filter by CRC hash"); + helptext.Add(" -ncrc=, --not-crc= Filter by not CRC hash"); + helptext.Add(" -md5=, --md5= Filter by MD5 hash"); + helptext.Add(" -nmd5=, --not-md5= Filter by not MD5 hash"); + helptext.Add(" -sha1=, --sha1= Filter by SHA-1 hash"); + helptext.Add(" -nsha1=, --not-sha1= Filter by not SHA-1 hash"); + helptext.Add(" -is=, --status= Include only items with a given status"); + helptext.Add(" Supported values are:"); + helptext.Add(" None, Good, BadDump, Nodump, Verified"); + helptext.Add(" -nis=, --not-status= Exclude items with a given status"); + helptext.Add(" Supported values are:"); + helptext.Add(" None, Good, BadDump, Nodump, Verified"); + helptext.Add(" -gt=, --game-type= Include only games with a given type"); + helptext.Add(" Supported values are:"); + helptext.Add(" None, Bios, Device, Mechanical"); + helptext.Add(" -ngt=, --not-gtype= Exclude only games with a given type"); + helptext.Add(" Supported values are:"); + helptext.Add(" None, Bios, Device, Mechanical"); + helptext.Add(" -run, --runnable Include only items that are marked runnable"); + helptext.Add(" -nrun, --not-run Include only items that are marked unrunnable"); + helptext.Add(" -out= Output directory (overridden by --inplace)"); + helptext.Add(" -mt={4} Amount of threads to use (-1 unlimted)"); + + + helptext.Add(""); + helptext.Add(barrier); + helptext.Add("Additional Notes:"); + + helptext.Add(""); + helptext.Add("All -diX, --diff-XX flags can be used with each other"); + + helptext.Add(""); + helptext.Add("Filter parameters game name, rom name, CRC, MD5, SHA-1 can"); + helptext.Add("do partial matches using asterisks as follows (case insensitive):"); + helptext.Add(" *00 means ends with '00'"); + helptext.Add(" 00* means starts with '00'"); + helptext.Add(" *00* means contains '00'"); + helptext.Add(" 00 means exactly equals '00'"); + + helptext.Add(""); + helptext.Add("Filter parameters for size can use postfixes for inputs:"); + helptext.Add(" e.g. 8kb => 8000 or 8kib => 8192"); + + helptext.Add(""); + helptext.Add("Most of the filter parameters allow for multiple inputs:"); + helptext.Add(" e.g. --game-name=foo --game-name=bar"); + + // Create the Verify feature + Feature verify = new Feature( + new List() { "-ve", "--verify" }, + "Verify a folder against DATs", + FeatureType.Flag, + null); + helptext.Add(" -dat= Input DAT to verify against"); + helptext.Add(" -t=, --temp= Set the temporary directory to use"); + helptext.Add(" -ho, --hash-only Check files by hash only"); + helptext.Add(" -qs, --quick Enable quick scanning of archives"); + helptext.Add(" -h=, --header= Set a header skipper to use, blank means all"); + + // Create the Verify Depot feature + Feature verifyDepot = new Feature( + new List() { "-ved", "--verify-depot" }, + "Verify a depot against DATs", + FeatureType.Flag, + null); + helptext.Add(" -dat= Input DAT to verify against"); + helptext.Add(" -t=, --temp= Set the temporary directory to use"); + helptext.Add(" -h=, --header= Set a header skipper to use, blank means all"); + + */ + + // Now, add all of the main features to the Help object + help.Add("Help", helpFeature); + help.Add("Script", script); + help.Add("DATFromDir", datFromDir); + help.Add("Extract", extract); + help.Add("Extension Split", extSplit); + help.Add("Hash Split", hashSplit); + help.Add("Level Split", levelSplit); + help.Add("Restore", restore); + help.Add("Sort", sort); + //help.Add("Sort Depot", sortDepot); + //help.Add("Stats", stats); + //help.Add("Type Split", typeSplit); + //help.Add("Update", update); + //help.Add("Verify", verify); + //help.Add("Verify Depot", verifyDepot); + + return help; + } + } +} diff --git a/SabreTools/SabreTools.cs b/SabreTools/SabreTools.cs index 39c3a236..74510a9d 100644 --- a/SabreTools/SabreTools.cs +++ b/SabreTools/SabreTools.cs @@ -4,6 +4,8 @@ using System.Linq; using SabreTools.Helper; using SabreTools.Helper.Data; +using SabreTools.Helper.Help; +using SabreTools.Helper.Resources; #if MONO using System.IO; @@ -53,6 +55,9 @@ namespace SabreTools return; } + // Create a new Help object for this program + //Help help = RetrieveHelp(); + // Feature flags bool datFromDir = false, extract = false, diff --git a/SabreTools/SabreTools.csproj b/SabreTools/SabreTools.csproj index 607b78d1..b5d891d6 100644 --- a/SabreTools/SabreTools.csproj +++ b/SabreTools/SabreTools.csproj @@ -122,6 +122,7 @@ +