mirror of
https://github.com/claunia/SabreTools.git
synced 2025-12-16 19:14:27 +00:00
[SabreTools.Library] Update folder name
This commit is contained in:
386
SabreTools.Library/Help/Feature.cs
Normal file
386
SabreTools.Library/Help/Feature.cs
Normal file
@@ -0,0 +1,386 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
using SabreTools.Helper.Data;
|
||||
|
||||
namespace SabreTools.Helper.Help
|
||||
{
|
||||
public class Feature
|
||||
{
|
||||
#region Private variables
|
||||
|
||||
private List<string> _flags;
|
||||
private string _description;
|
||||
private FeatureType _featureType;
|
||||
private Dictionary<string, Feature> _features;
|
||||
private List<string> _additionalNotes;
|
||||
private bool _foundOnce = false;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
public Feature()
|
||||
{
|
||||
_flags = new List<string>();
|
||||
_description = null;
|
||||
_featureType = FeatureType.Flag;
|
||||
_features = new Dictionary<string, Feature>();
|
||||
_additionalNotes = new List<string>();
|
||||
}
|
||||
|
||||
public Feature(string flag, string description, FeatureType featureType, List<string> additionalNotes)
|
||||
{
|
||||
List<string> flags = new List<string>();
|
||||
flags.Add(flag);
|
||||
_flags = flags;
|
||||
_description = description;
|
||||
_featureType = featureType;
|
||||
_features = new Dictionary<string, Feature>();
|
||||
_additionalNotes = additionalNotes;
|
||||
}
|
||||
|
||||
public Feature(List<string> flags, string description, FeatureType featureType, List<string> additionalNotes)
|
||||
{
|
||||
_flags = flags;
|
||||
_description = description;
|
||||
_featureType = featureType;
|
||||
_features = new Dictionary<string, Feature>();
|
||||
_additionalNotes = additionalNotes;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Accessors
|
||||
|
||||
/// <summary>
|
||||
/// Directly address a given subfeature
|
||||
/// </summary>
|
||||
public Feature this[string name]
|
||||
{
|
||||
get { return _features[name]; }
|
||||
set { _features[name] = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add a new feature for this feature
|
||||
/// </summary>
|
||||
/// <param name="name">Name of the feature to add</param>
|
||||
/// <param name="feature"></param>
|
||||
public void AddFeature(string name, Feature feature)
|
||||
{
|
||||
if (_features == null)
|
||||
{
|
||||
_features = new Dictionary<string, Feature>();
|
||||
}
|
||||
|
||||
lock(_features)
|
||||
{
|
||||
if (!_features.ContainsKey(name))
|
||||
{
|
||||
_features.Add(name, feature);
|
||||
}
|
||||
else
|
||||
{
|
||||
_features[name] = feature;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add a new flag for this feature
|
||||
/// </summary>
|
||||
/// <param name="flag">Flag to add for this feature</param>
|
||||
public void AddFlag(string flag)
|
||||
{
|
||||
if (_flags == null)
|
||||
{
|
||||
_flags = new List<string>();
|
||||
}
|
||||
|
||||
lock (_flags)
|
||||
{
|
||||
_flags.Add(flag);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add a set of new flags for this feature
|
||||
/// </summary>
|
||||
/// <param name="flags">List of flags to add to this feature</param>
|
||||
public void AddFlags(List<string> flags)
|
||||
{
|
||||
if (_flags == null)
|
||||
{
|
||||
_flags = new List<string>();
|
||||
}
|
||||
|
||||
lock (_flags)
|
||||
{
|
||||
_flags.AddRange(flags);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add a new additional note to this feature
|
||||
/// </summary>
|
||||
/// <param name="note">Note to add for this feature</param>
|
||||
public void AddNote(string note)
|
||||
{
|
||||
if (_additionalNotes == null)
|
||||
{
|
||||
_additionalNotes = new List<string>();
|
||||
}
|
||||
|
||||
lock (_additionalNotes)
|
||||
{
|
||||
_additionalNotes.Add(note);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add a set of new notes for this feature
|
||||
/// </summary>
|
||||
/// <param name="notes">List of notes to add to this feature</param>
|
||||
public void AddNotes(List<string> notes)
|
||||
{
|
||||
if (_additionalNotes == null)
|
||||
{
|
||||
_additionalNotes = new List<string>();
|
||||
}
|
||||
|
||||
lock (_additionalNotes)
|
||||
{
|
||||
_additionalNotes.AddRange(notes);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns if a flag exists for the current feature
|
||||
/// </summary>
|
||||
/// <param name="name">Name of the flag to check</param>
|
||||
/// <returns>True if the flag was found, false otherwise</returns>
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns if the feature contains a flag that starts with the given character
|
||||
/// </summary>
|
||||
/// <param name="c">Character to check against</param>
|
||||
/// <returns>True if the flag was found, false otherwise</returns>
|
||||
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
|
||||
|
||||
/// <summary>
|
||||
/// Output this feature only
|
||||
/// </summary>
|
||||
/// <param name="pre">Positive number representing number of spaces to put in front of the feature</param>
|
||||
/// <param name="midpoint">Positive number representing the column where the description should start</param>
|
||||
public List<string> Output(int pre = 0, int midpoint = 0)
|
||||
{
|
||||
// Create the output list
|
||||
List<string> outputList = new List<string>();
|
||||
|
||||
// Build the output string first
|
||||
string output = "";
|
||||
|
||||
// Add the pre-space first
|
||||
string prespace = "";
|
||||
for (int i = 0; i < pre; i++)
|
||||
{
|
||||
prespace += " ";
|
||||
}
|
||||
output += prespace;
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Output this feature and all subfeatures
|
||||
/// </summary>
|
||||
/// <param name="tabLevel">Level of indentation for this feature</param>
|
||||
/// <param name="pre">Positive number representing number of spaces to put in front of the feature</param>
|
||||
/// <param name="midpoint">Positive number representing the column where the description should start</param>
|
||||
public List<string> OutputRecursive(int tabLevel, int pre = 0, int midpoint = 0)
|
||||
{
|
||||
// Create the output list
|
||||
List<string> outputList = new List<string>();
|
||||
|
||||
// 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
|
||||
string prespace = "";
|
||||
for (int i = 0; i < preAdjusted; i++)
|
||||
{
|
||||
prespace += " ";
|
||||
}
|
||||
output += prespace;
|
||||
|
||||
// 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));
|
||||
}
|
||||
|
||||
// Finally, let's append all additional notes
|
||||
if (_additionalNotes != null && _additionalNotes.Count > 0)
|
||||
{
|
||||
foreach (string note in _additionalNotes)
|
||||
{
|
||||
outputList.Add(prespace + note);
|
||||
}
|
||||
}
|
||||
|
||||
return outputList;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validate whether a flag is valid for this feature or not
|
||||
/// </summary>
|
||||
/// <param name="input">Input to check against</param>
|
||||
/// <param name="exact">True if just this feature should be checked, false if all subfeatures are checked as well</param>
|
||||
/// <returns>True if the flag was valid, false otherwise</returns>
|
||||
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;
|
||||
}
|
||||
|
||||
// If we're not valid at this point, we want to check if this flag is a file or a folder
|
||||
if (!valid)
|
||||
{
|
||||
valid = File.Exists(input) || Directory.Exists(input);
|
||||
}
|
||||
|
||||
return valid;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
300
SabreTools.Library/Help/Help.cs
Normal file
300
SabreTools.Library/Help/Help.cs
Normal file
@@ -0,0 +1,300 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace SabreTools.Helper.Help
|
||||
{
|
||||
public class Help
|
||||
{
|
||||
#region Private variables
|
||||
|
||||
private List<string> _header;
|
||||
private Dictionary<string, Feature> _features;
|
||||
private static string _barrier = "-----------------------------------------";
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
public Help()
|
||||
{
|
||||
_header = new List<string>();
|
||||
_features = new Dictionary<string, Feature>();
|
||||
}
|
||||
|
||||
public Help(List<string> header)
|
||||
{
|
||||
_header = header;
|
||||
_features = new Dictionary<string, Feature>();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Accessors
|
||||
|
||||
public Feature this[string name]
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_features == null)
|
||||
{
|
||||
_features = new Dictionary<string, Feature>();
|
||||
}
|
||||
|
||||
if (!_features.ContainsKey(name))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return _features[name];
|
||||
}
|
||||
set
|
||||
{
|
||||
if (_features == null)
|
||||
{
|
||||
_features = new Dictionary<string, Feature>();
|
||||
}
|
||||
|
||||
if (_features.ContainsKey(name))
|
||||
{
|
||||
_features[name] = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
_features.Add(name, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add a new feature to the help
|
||||
/// </summary>
|
||||
/// <param name="name">Name of the feature to add</param>
|
||||
/// <param name="feature">Feature object to map to</param>
|
||||
public void Add(string name, Feature feature)
|
||||
{
|
||||
if (_features == null)
|
||||
{
|
||||
_features = new Dictionary<string, Feature>();
|
||||
}
|
||||
|
||||
lock (_features)
|
||||
{
|
||||
_features.Add(name, feature);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Instance Methods
|
||||
|
||||
/// <summary>
|
||||
/// Get the feature name for a given flag or short name
|
||||
/// </summary>
|
||||
/// <returns>Feature name</returns>
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Output top-level features only
|
||||
/// </summary>
|
||||
public void OutputGenericHelp()
|
||||
{
|
||||
// Start building the output list
|
||||
List<string> output = new List<string>();
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Output all features recursively
|
||||
/// </summary>
|
||||
public void OutputAllHelp()
|
||||
{
|
||||
// Start building the output list
|
||||
List<string> output = new List<string>();
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Output the SabreTools suite credits
|
||||
/// </summary>
|
||||
public void OutputCredits()
|
||||
{
|
||||
List<string> credits = new List<string>();
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Output a single feature recursively
|
||||
/// </summary>
|
||||
public void OutputIndividualFeature(string featurename)
|
||||
{
|
||||
// Start building the output list
|
||||
List<string> output = new List<string>();
|
||||
|
||||
// Now try to find the feature that has the name included
|
||||
string realname = null;
|
||||
List<string> startsWith = new List<string>();
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check if a flag is a top-level (main application) flag
|
||||
/// </summary>
|
||||
/// <param name="flag">Name of the flag to check</param>
|
||||
/// <returns>True if the feature was found, false otherwise</returns>
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write out the help text with pauses, if needed
|
||||
/// </summary>
|
||||
/// <param name="helptext"></param>
|
||||
private void WriteOutWithPauses(List<string> 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();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Pause on console output
|
||||
/// </summary>
|
||||
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
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user