using System; using System.Collections.Generic; using SabreTools.Library.Data; namespace SabreTools.Library.Help { // TODO: Parse and return flags from arguments // TODO: Perform partial matching to find potentially similar features public class Help { #region Private variables private List _header; private Dictionary _features; private static string _barrier = "-----------------------------------------"; #endregion #region Constructors public Help() { _header = new List(); _features = new Dictionary(); } public Help(List header) { _header = header; _features = new Dictionary(); } #endregion #region Accessors public Feature this[string name] { get { if (_features == null) { _features = new Dictionary(); } if (!_features.ContainsKey(name)) { return null; } return _features[name]; } set { if (_features == null) { _features = new Dictionary(); } if (_features.ContainsKey(name)) { _features[name] = value; } else { _features.Add(name, value); } } } /// /// 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 /// /// Get the feature name for a given flag or short name /// /// Feature name public string GetFeatureName(string name) { string feature = ""; // Loop through the features foreach (string featureName in _features.Keys) { if (_features[featureName].ValidateInput(name, exact: true)) { feature = featureName; break; } } return feature; } /// /// 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 the SabreTools suite credits /// public void OutputCredits() { List credits = new List(); credits.Add(_barrier); credits.Add("Credits"); credits.Add(_barrier); credits.Add(""); credits.Add("Programmer / Lead: Matt Nadareski (darksabre76)"); credits.Add("Additional code: emuLOAD, @tractivo, motoschifo"); credits.Add("Testing: emuLOAD, @tractivo, Kludge, Obiwantje, edc"); credits.Add("Suggestions: edc, AcidX, Amiga12, EliUmniCk"); credits.Add("Based on work by: The Wizard of DATz"); WriteOutWithPauses(credits); } /// /// Output a single feature recursively /// public void OutputIndividualFeature(string featurename) { // Start building the output list List output = new List(); // 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); } /// /// Check if a flag is a top-level (main application) flag /// /// Name of the flag to check /// True if the feature was found, false otherwise public bool TopLevelFlag(string flag) { bool success = false; // Loop through the features and check foreach (string feature in _features.Keys) { if (_features[feature].ValidateInput(flag, exact: true)) { success = true; break; } } return success; } /// /// Retrieve a list of enabled features /// /// List of Features representing what is enabled public List GetEnabledFeatures() { List enabled = new List(); // Loop through the features foreach(KeyValuePair feature in _features) { enabled.AddRange(GetEnabledSubfeatures(feature.Value)); } return enabled; } /// /// Retrieve a nested list of subfeatures from the current feature /// /// Feature with possible subfeatures to test /// List of Features representing what is enabled private List GetEnabledSubfeatures(Feature feature) { List enabled = new List(); // First determine if the current feature is enabled if (feature.IsEnabled()) { enabled.Add(feature); } // Now loop through the subfeatures recursively foreach (KeyValuePair sub in _features) { enabled.AddRange(GetEnabledSubfeatures(sub.Value)); } return enabled; } /// /// 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; for (int line = 0; line < helptext.Count; line++) { string help = helptext[line]; Console.WriteLine(help); i++; // If we're not being redirected and we reached the size of the screen, pause if (i == Console.WindowHeight - 3 && line != helptext.Count - 1) { 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(); } } #endregion } }