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