From d215b09d72f542a4071cb3810c19a39206174c5b Mon Sep 17 00:00:00 2001 From: clragon Date: Mon, 21 Sep 2020 00:03:41 +0200 Subject: [PATCH] updated menu engine to CLOE --- ExeToBat/BatGen.cs | 605 ++++++++++++++++++++++++--------------------- 1 file changed, 321 insertions(+), 284 deletions(-) diff --git a/ExeToBat/BatGen.cs b/ExeToBat/BatGen.cs index 9acae8e..71d65da 100644 --- a/ExeToBat/BatGen.cs +++ b/ExeToBat/BatGen.cs @@ -11,83 +11,71 @@ namespace ExeToBat public static List Sources = new List(); - static void Main(string[] args) - { - MainMenu(); - } + static void Main() => MainMenu(); static void MainMenu() { - List options = new List { "Files", "Generate" }; + Dictionary options = new Dictionary { + { "Files", ChooseSource }, + { "Generate", () => BuildBat(Sources, "output.bat") } + }; - void DisplayTitle(List Options) + new ListMenu(options.Keys.ToList()) { - Console.WriteLine("ExeToBat > Main"); - } - - void DisplayEntry(List Options, string o, int index, int i) - { - Console.WriteLine("[{0}] {1}", i, o); - } - - bool HandleEntry(List Options, int index) - { - switch (Options[index]) + DisplayTitle = (List Options) => Console.WriteLine("ExeToBat > Main"), + DisplayEntry = (List Options, int index, int i) => { - case var i when i.Equals("Files"): - ChooseSource(); - break; - - case var i when i.Equals("Generate"): - BuildBat(Sources, "output.bat"); - break; - - default: + Console.WriteLine("[{0}] {1}", i, Options[index]); + }, + HandleEntry = (List Options, int index) => + { + if (options.ContainsKey(Options[index])) + { + options[Options[index]](); + } + else + { ResetInput(); - break; - } - return false; - } + } - ListToMenu(options, HandleEntry, DisplayTitle, DisplayEntry, ExitEntry:"Exit"); + return false; + }, + ExitEntry = "Exit", + + }.Show(); } static void ChooseSource() { - void DisplayTitle(List sources) + new ListMenu(Sources) { - Console.WriteLine("ExeToBat > Main > Files"); - Console.WriteLine("[{0}] ({1})", Convert.ToString(0).PadLeft(Convert.ToString(sources.Count).Length, ' '), "Add Files"); - } + DisplayTitle = (List sources) => + { + Console.WriteLine("ExeToBat > Main > Files"); + Console.WriteLine("[{0}] ({1})", Convert.ToString(0).PadLeft(Convert.ToString(sources.Count).Length, ' '), "Add Files"); + }, + DisplayEntry = (List sources, int index, int i) => + Console.WriteLine("[{0}] {1}", + Convert.ToString(i).PadLeft( + Convert.ToString(sources.Count).Length, ' '), + Path.GetFileName(sources[index].File)), + ZeroEntry = (List sources) => + { + AddSource(); + return false; + }, + HandleEntry = (List sources, int index) => + { + ManageSource(sources[index]); + return false; + }, + RefreshEntries = (List sources) => Sources, - void DisplayEntry(List sources, SourceFile source, int index, int i) - { - Console.WriteLine("[{0}] {1}", Convert.ToString(i).PadLeft(Convert.ToString(sources.Count).Length, ' '), Path.GetFileName(source.File)); - } - - bool ZeroMethod(List sources) - { - AddSource(); - return false; - } - - bool HandleEntry(List sources, int index) - { - ManageSource(sources[index]); - return false; - } - - List UpdateObjects(List sources) - { - return Sources; - } - - ListToMenu(Sources, HandleEntry, DisplayTitle, DisplayEntry, ZeroMethod, UpdateObjects); + }.Show(); } static void AddSource() { - string input = ""; bool IsInputValid = false; while (!IsInputValid) { @@ -96,7 +84,7 @@ namespace ExeToBat Console.WriteLine("ExeToBat > Main > Files > Add"); Console.Write("\n"); Console.Write("{0}> ", "File/Folder"); - input = Console.ReadLine(); + string input = Console.ReadLine(); input.Trim(); input = input.Replace("\"", ""); @@ -131,117 +119,106 @@ namespace ExeToBat static void ManageSource(SourceFile source) { - List options = new List { "Edit", "Position", "Delete" }; - - void DisplayTitle(List Options) + Dictionary> options = new Dictionary> { - Console.WriteLine("ExeToBat > Main > Files > {0}", Path.GetFileName(source.File)); - } - - void DisplayEntry(List Options, string o, int index, int i) - { - Console.WriteLine("[{0}] {1}", i, o); - } - - bool HandleEntry(List Options, int index) - { - switch (Options[index]) - { - case var i when i.Equals("Edit"): - ModifySource(source); - break; - - case var i when i.Equals("Position"): - EditPosition(source); - break; - - case var i when i.Equals("Delete"): - Sources.Remove(source); - return true; - - default: - ResetInput(); - break; + {"Edit", () => { + ModifySource(source); + return false; } - return false; - } + }, + { "Position", () => { + EditPosition(source); + return false; + } + }, + { "Delete", () => { + Sources.Remove(source); + return true; + } + }, + }; - ListToMenu(options, HandleEntry, DisplayTitle, DisplayEntry); + new ListMenu(options.Keys.ToList()) + { + DisplayTitle = (List Options) => Console.WriteLine("ExeToBat > Main > Files > {0}", Path.GetFileName(source.File)), + DisplayEntry = (List Options, int index, int i) => Console.WriteLine("[{0}] {1}", i, Options[index]), + HandleEntry = (List Options, int index) => + { + if (options.ContainsKey(Options[index])) + { + return options[Options[index]](); + } + else + { + ResetInput(); + } + + return false; + }, + + }.Show(); } static void ModifySource(SourceFile source) { - List options() { - List opts = new List { "File", "Extraction directory", "Execute after extraction" }; - if (source.Execute) { opts.AddRange( new List { "Parameters", "Wait for exit" } ); } - if (source.Wait) { opts.Add("Delete after execution"); } + // this could be solved better with an enum + + Dictionary options() + { + Dictionary opts = new Dictionary { + {"File", () => { } }, + {"Extraction directory", () => EditExtraction(source)}, + {"Execute after extraction", () => source.Execute = !source.Execute }, + }; + if (source.Execute) + { + opts.Add("Parameters", () => EditParameters(source)); + opts.Add("Wait for exit", () => source.Wait = !source.Wait); + } + if (source.Execute && source.Wait) { opts.Add("Delete after execution", () => source.Delete = !source.Delete); } return opts; } Dictionary ValueMap = new Dictionary { { "File", "File" }, + { "Extraction directory", "Directory" }, { "Execute after extraction", "Execute" }, + { "Parameters", "Parameters" }, { "Wait for exit", "Wait"}, { "Delete after execution", "Delete"}, - { "Extraction directory", "Directory" }, - { "Parameters", "Parameters" }, }; - void DisplayTitle(List Options) + new ListMenu(options().Keys.ToList()) { - Console.WriteLine("ExeToBat > Main > Files > {0} > Edit", Path.GetFileName(source.File)); - } - - int MaxLength = options().Select(x => x.Length).Max(); - void DisplayEntry(List Options, string o, int index, int i) - { - Console.WriteLine("[{0}] {1} | {2}", i, o.PadRight(MaxLength, ' '), source.GetType().GetProperty(ValueMap[o]).GetValue(source).ToString()); - } - - bool HandleEntry(List Options, int index) - { - switch (Options[index]) + DisplayTitle = (List Options) => Console.WriteLine("ExeToBat > Main > Files > {0} > Edit", Path.GetFileName(source.File)), + DisplayEntry = (List Options, int index, int i) => { - case var i when i.Equals("File"): - - break; - - case var i when i.Equals("Execute after extraction"): - source.Execute = !source.Execute; - break; - - case var i when i.Equals("Extraction directory"): - EditExtraction(source); - break; - - case var i when i.Equals("Parameters"): - EditParameters(source); - break; - - case var i when i.Equals("Wait for exit"): - source.Wait = !source.Wait; - break; - - case var i when i.Equals("Delete after execution"): - source.Delete = !source.Delete; - break; - - default: + int MaxLength = options().Keys.Select(x => x.Length).Max(); + Console.WriteLine("[{0}] {1} | {2}", i, Options[index].PadRight(MaxLength, ' '), source.GetType().GetProperty(ValueMap[Options[index]]).GetValue(source).ToString()); + }, + HandleEntry = (List Options, int index) => + { + if (options().ContainsKey(Options[index])) + { + options()[Options[index]](); + } + else + { ResetInput(); - break; - } - return false; - } + } - ListToMenu(options(), HandleEntry, DisplayTitle, DisplayEntry); + return false; + }, + RefreshEntries = (List Options) => options().Keys.ToList(), + + }.Show(); } static void EditExtraction(SourceFile source) { - string input = ""; bool IsInputValid = false; while (!IsInputValid) { @@ -253,7 +230,7 @@ namespace ExeToBat Console.WriteLine("https://ss64.com/nt/syntax-args.html"); Console.Write("\n"); Console.Write("{0}> ", "Directory"); - input = Console.ReadLine(); + string input = Console.ReadLine(); input.Trim(); if (!string.IsNullOrEmpty(input)) @@ -270,7 +247,6 @@ namespace ExeToBat static void EditParameters(SourceFile source) { - string input = ""; bool IsInputValid = false; while (!IsInputValid) { @@ -278,7 +254,7 @@ namespace ExeToBat Console.WriteLine("ExeToBat > Main > Files > {0} > Edit > Parameters", Path.GetFileName(source.File)); Console.Write("\n"); Console.Write("{0}> ", "Parameters"); - input = Console.ReadLine(); + string input = Console.ReadLine(); input.Trim(); if (!string.IsNullOrEmpty(input)) @@ -295,8 +271,6 @@ namespace ExeToBat static void EditPosition(SourceFile source) { - string input = ""; - int index = -1; bool IsInputValid = false; while (!IsInputValid) { @@ -305,9 +279,9 @@ namespace ExeToBat Console.Write("\n"); Console.Write("{0}> ", "New index"); - input = Console.ReadLine(); + string input = Console.ReadLine(); - if (int.TryParse(input, out index)) + if (int.TryParse(input, out int index)) { if (index < Sources.Count) { @@ -339,7 +313,7 @@ namespace ExeToBat Console.Clear(); Console.WriteLine("ExeToBat > Main > Generate"); - if(Sources.Any()) + if (Sources.Any()) { using (StreamWriter writer = new StreamWriter(outputFile)) { @@ -411,7 +385,7 @@ namespace ExeToBat Wait(500); } - + } @@ -424,7 +398,7 @@ namespace ExeToBat public string Resource { get; set; } = GenTemp(); public string Directory { get; set; } = "%~dp0"; public string Parameters { get; set; } = ""; - + public SourceFile(string file) { @@ -433,7 +407,7 @@ namespace ExeToBat static public string GenTemp() { - return string.Format("{0}{1}{2}", "res_", new Random().Next(1000, 10000), ".b64"); + return string.Format($"res_{new Random().Next(1000, 10000)}.b64"); } } @@ -453,7 +427,7 @@ namespace ExeToBat int startIndex = chunkSize * i; stringArray[i] = toSplit.Substring(startIndex, lengthToUse); - lengthRemaining = lengthRemaining - lengthToUse; + lengthRemaining -= lengthToUse; } return stringArray; @@ -469,171 +443,234 @@ namespace ExeToBat } } - - /// - /// A function that displays a list as an enumerated menu on the Cli. Items can be chosen and will be processed by passed functions. - /// Rest in peace, Cloe. - /// - /// A list of objects that will be displayed as choices. - /// The function that displays the title. It should include displaying the 0th entry if you want to use it. - /// The function that displays an entry. The default function can display strings, for any other objects you will have to pass a custom one. - /// The function that handles the chosen entry. - /// The 0th entry. It is different from the passed list and can be used for example to create new entries. - /// Pass a function that will handle updating the list of objects here. - /// Defines if the user can exit the menu. - /// The string that is displayed for the entry that closes the menu. - public static void ListToMenu(List Entries, Func, int, bool> HandleEntry, Action> DisplayTitle = null, Action, T, int, int> DisplayEntry = null, Func, bool> ZeroEntry = null, Func, List> RefreshEntries = null, bool UserCanAbort = true, string ExitEntry = null) + public class ListMenu { - DisplayTitle = DisplayTitle ?? ((List entries) => { }); - DisplayEntry = DisplayEntry ?? ((List entries, T entry, int index_, int num) => { Console.WriteLine("[{0}] {1}", Convert.ToString(num).PadLeft(Convert.ToString(entries.Count).Length, ' '), entry); }); - RefreshEntries = RefreshEntries ?? ((List entries) => { return entries; }); - ZeroEntry = ZeroEntry ?? ((List entries) => { ResetInput(); return false; }); - ExitEntry = ExitEntry ?? "Back"; + /// + /// CLOE (Command-line List Options Enumerator). + /// Turns a List into a menu of options. Each list item is asigned a number. Provides several callbacks to customise the menu. + /// + /// List of objects you want to display + public ListMenu(List entries) + { + Entries = entries; + } - char ExitKey = 'q'; - string Prompt = "Choose"; + /// + /// The prompt that is displayed to the user. + /// + public string Prompt = "Choose"; + + /// + /// The string to be displayed for the option to exit the menu. + /// + public string ExitEntry = "Back"; + + /// + /// The key the user has to press to exit the menu. + /// + public char ExitKey = 'q'; + + /// + /// Wether or not the user can exit the menu. + /// + public bool UserCanExit = true; - string readInput = string.Empty; - bool MenuExitIsPending = false; - while (!MenuExitIsPending) + private List Entries; + + /// + /// The function that processes the chosen menu entries. + /// + public Func, int, bool> HandleEntry = (entries, index) => { Console.Clear(); - int printedEntries = 0; - Entries = RefreshEntries(Entries); - DisplayTitle(Entries); - if (Entries.Any()) + Console.WriteLine(entries[index]); + Wait(200); + return false; + }; + + /// + /// The function that displays the menu title. + /// + public Action> DisplayTitle = (entries) => { }; + + /// + /// The function that displays the entry to the user. + /// + public Action, int, int> DisplayEntry = (entries, index, num) => + { + Console.WriteLine("[{0}] {1}", Convert.ToString(num).PadLeft(Convert.ToString(entries.Count).Length, ' '), entries[index]); + }; + + /// + /// The function to update the list of entries. + /// + public Func, List> RefreshEntries = (entries) => + { + return entries; + }; + + /// + /// The function that is called when 0th entry in the list is chosen. + /// Display this entry with the title function. + /// + public Func, bool> ZeroEntry = (entries) => + { + ResetInput(); + return false; + }; + + /// + /// Display the menu. + /// + /// + public ListMenu Show() + { + string readInput = string.Empty; + bool MenuExitIsPending = false; + while (!MenuExitIsPending) { - int num = 0; - foreach (T entry in Entries) + Console.Clear(); + int printedEntries = 0; + Entries = RefreshEntries(Entries); + DisplayTitle(Entries); + if (Entries.Any()) { - num++; - if (string.IsNullOrEmpty(readInput) || Convert.ToString(num).StartsWith(readInput)) + int num = 0; + foreach (T entry in Entries) { - DisplayEntry(Entries, entry, Entries.IndexOf(entry), num); - printedEntries++; - } - - if (Entries.Count > Console.WindowHeight - 5) - { - if (printedEntries >= Console.WindowHeight - (5 + 1)) + num++; + if (string.IsNullOrEmpty(readInput) || Convert.ToString(num).StartsWith(readInput)) { - Console.WriteLine("[{0}] +{1}", ".".PadLeft(Convert.ToString(Entries.Count).Length, '.'), Entries.Count); - break; + DisplayEntry(Entries, Entries.IndexOf(entry), num); + printedEntries++; } - } - else - { - if (printedEntries == Console.WindowHeight - 5) - { - break; - } - } + if (Entries.Count > Console.WindowHeight - 5) + { + if (printedEntries >= Console.WindowHeight - (5 + 1)) + { + Console.WriteLine("[{0}] +{1}", ".".PadLeft(Convert.ToString(Entries.Count).Length, '.'), Entries.Count); + break; + } + } + else + { + if (printedEntries == Console.WindowHeight - 5) + { + break; + } + } + + } } - } - if (UserCanAbort) - { - Console.WriteLine("[{0}] {1}", Convert.ToString(ExitKey).PadLeft(Convert.ToString(Entries.Count).Length, ' '), ExitEntry); - } - - Console.WriteLine(); - - bool InputIsValid = false; - while (!InputIsValid) - { - Console.Write("{0}> {1}", Prompt, readInput); - ConsoleKeyInfo input = Console.ReadKey(); - Wait(20); - int choiceNum = -1; - switch (input) + if (UserCanExit) { - case var key when key.KeyChar.Equals(ExitKey): - if (UserCanAbort) - { - Console.WriteLine(); - InputIsValid = true; - MenuExitIsPending = true; - } - else - { - Console.WriteLine(); - ResetInput(); - } - break; + Console.WriteLine("[{0}] {1}", Convert.ToString(ExitKey).PadLeft(Convert.ToString(Entries.Count).Length, ' '), ExitEntry); + } - case var key when key.Key.Equals(ConsoleKey.Backspace): - if (!string.IsNullOrEmpty(readInput)) - { - Console.Write("\b"); - readInput = readInput.Remove(readInput.Length - 1); - } - InputIsValid = true; - break; + Console.WriteLine(); - case var key when key.Key.Equals(ConsoleKey.Enter): - if (!string.IsNullOrEmpty(readInput)) - { - if (HandleEntry(Entries, (Convert.ToInt32(readInput) - 1))) + bool InputIsValid = false; + while (!InputIsValid) + { + Console.Write("{0}> {1}", Prompt, readInput); + ConsoleKeyInfo input = Console.ReadKey(); + Wait(20); + int choiceNum = -1; + switch (input) + { + case var key when key.KeyChar.Equals(ExitKey): + if (UserCanExit) { + Console.WriteLine(); + InputIsValid = true; MenuExitIsPending = true; } - readInput = string.Empty; - } - InputIsValid = true; - break; - - case var key when int.TryParse(key.KeyChar.ToString(), out choiceNum): - Console.WriteLine(); - if (string.IsNullOrEmpty(readInput) && choiceNum.Equals(0)) - { - InputIsValid = true; - if (ZeroEntry(Entries)) + else { - MenuExitIsPending = true; + Console.WriteLine(); + ResetInput(); } - } - else - { - if (Convert.ToInt32(readInput + Convert.ToString(choiceNum)) <= Entries.Count) + break; + + case var key when key.Key.Equals(ConsoleKey.Backspace): + if (!string.IsNullOrEmpty(readInput)) + { + Console.Write("\b"); + readInput = readInput.Remove(readInput.Length - 1); + } + InputIsValid = true; + break; + + case var key when key.Key.Equals(ConsoleKey.Enter): + if (!string.IsNullOrEmpty(readInput)) + { + if (HandleEntry(Entries, (Convert.ToInt32(readInput) - 1))) + { + MenuExitIsPending = true; + } + readInput = string.Empty; + } + InputIsValid = true; + break; + + case var key when int.TryParse(key.KeyChar.ToString(), out choiceNum): + Console.WriteLine(); + if (string.IsNullOrEmpty(readInput) && choiceNum.Equals(0)) { InputIsValid = true; - int matchingEntries = 0; - readInput = new System.Text.StringBuilder().Append(readInput).Append(Convert.ToString(choiceNum)).ToString(); - for (int i = 0; i < Entries.Count; i++) + if (ZeroEntry(Entries)) { - if (Convert.ToString(i + 1).StartsWith(readInput) || Convert.ToString(i + 1) == readInput) { matchingEntries++; } - } - if ((readInput.Length == Convert.ToString(Entries.Count).Length) || (matchingEntries == 1)) - { - if (HandleEntry(Entries, (Convert.ToInt32(readInput) - 1))) - { - MenuExitIsPending = true; - } - readInput = string.Empty; + MenuExitIsPending = true; } } else { - ResetInput(); + if (Convert.ToInt32(readInput + Convert.ToString(choiceNum)) <= Entries.Count) + { + InputIsValid = true; + int matchingEntries = 0; + readInput = new System.Text.StringBuilder().Append(readInput).Append(Convert.ToString(choiceNum)).ToString(); + for (int i = 0; i < Entries.Count; i++) + { + if (Convert.ToString(i + 1).StartsWith(readInput) || Convert.ToString(i + 1) == readInput) { matchingEntries++; } + } + if ((readInput.Length == Convert.ToString(Entries.Count).Length) || (matchingEntries == 1)) + { + if (HandleEntry(Entries, (Convert.ToInt32(readInput) - 1))) + { + MenuExitIsPending = true; + } + readInput = string.Empty; + } + } + else + { + ResetInput(); + } } - } - break; + break; - default: - Console.WriteLine(); - ResetInput(); - break; + default: + Console.WriteLine(); + ResetInput(); + break; + } } } - + return this; } } - - + /// + /// A simple template to create Yes or No menus. + /// + /// The title of the menu. + /// The function to be called upon Yes + /// The function to be called upon No public static void YesNoMenu(string title, Action Yes, Action No) { bool IsInputValid = false; @@ -679,5 +716,5 @@ namespace ExeToBat } } - + }