See More

using BytecodeApi.Extensions; namespace BytecodeApi.ConsoleUI; ///

/// Class that retrieves user input from the in form of questions or confirmations. /// public static class ConsoleInput { /// /// Gets or sets the global theme for the class. /// public static ConsoleInputTheme Theme { get; set; } static ConsoleInput() { Theme = new(); } /// /// Writes to the console and prompts the user to input a . This process is repeated, until the entered is not empty. /// /// A to display before the user input prompt. /// /// The text that the user has entered. This is not empty. /// public static string Text(string question) { Check.ArgumentNull(question); Check.ArgumentNull(Theme); Check.ArgumentNull(Theme.QuestionStyle); Check.ArgumentNull(Theme.UserInputStyle); Flush(); string text; do { Theme.QuestionStyle.Write(question); Theme.UserInputStyle.Write(" "); text = Theme.UserInputStyle.ReadLine().Trim(); } while (text == ""); return text; } /// /// Writes to the console and prompts the user to input yes ("y") or no ("n"). /// /// A to display before the user input prompt. /// /// , if the user selected yes; /// , if the user selected no. /// public static bool Confirmation(string question) { return Confirmation(question, null); } /// /// Writes to the console and prompts the user to input yes ("y") or no ("n"). /// /// A to display before the user input prompt. /// A value that is returned, if the user did not enter any text, or to require the user to input yes or no. /// /// , if the user selected yes; /// , if the user selected no. /// public static bool Confirmation(string question, bool? defaultChoice) { Check.ArgumentNull(question); Check.ArgumentNull(Theme); Check.ArgumentNull(Theme.QuestionStyle); Check.ArgumentNull(Theme.UserInputStyle); Check.ArgumentNull(Theme.ConfirmationPostfix); Check.ArgumentNull(Theme.ConfirmationPostfixDefaultYes); Check.ArgumentNull(Theme.ConfirmationPostfixDefaultNo); Check.ArgumentNull(Theme.ConfirmationAnswerYes); Check.ArgumentEx.StringNotEmpty(Theme.ConfirmationAnswerYes); Check.ArgumentNull(Theme.ConfirmationAnswerNo); Check.ArgumentEx.StringNotEmpty(Theme.ConfirmationAnswerNo); string defaultChoiceString = defaultChoice switch { null => Theme.ConfirmationPostfix, true => Theme.ConfirmationPostfixDefaultYes, false => Theme.ConfirmationPostfixDefaultNo }; Flush(); bool? choice; do { Theme.QuestionStyle.Write($"{question} {defaultChoiceString}?"); Theme.UserInputStyle.Write(" "); string answer = Theme.UserInputStyle.ReadLine().Trim(); if (answer == "") choice = defaultChoice; else if (answer.Equals(Theme.ConfirmationAnswerYes, StringComparison.OrdinalIgnoreCase)) choice = true; else if (answer.Equals(Theme.ConfirmationAnswerNo, StringComparison.OrdinalIgnoreCase)) choice = false; else choice = null; } while (choice == null); return choice.Value; } /// /// Writes and an ordered list with to the console and prompts the user to select an option. /// /// A to display before the user input prompt. /// A [] with options that the user can select from. /// /// A one-based index within that represents the user selection. /// public static int Select(string question, params string[] options) { Check.ArgumentNull(question); Check.ArgumentNull(options); Check.ArgumentEx.ArrayValuesNotNull(options); Check.ArgumentNull(Theme); Check.ArgumentNull(Theme.QuestionStyle); Check.ArgumentNull(Theme.SelectOptionsStyle); Check.ArgumentNull(Theme.UserInputStyle); Flush(); Theme.QuestionStyle.WriteLine(question); for (int i = 0; i < options.Length; i++) { Theme.SelectOptionsStyle.WriteLine($" [{i + 1}] {options[i]}"); } while (true) { Theme.QuestionStyle.Write(Theme.SelectOptionsPromptText); Theme.UserInputStyle.Write(" "); if (Theme.UserInputStyle.ReadLine().ToInt32OrNull() is int selection && selection >= 1 && selection <= options.Length) { return selection; } } } private static void Flush() { // Important: If the user presses return, this would skip a confirmation that appears even a minute later. // So, flush the input buffer directly before prompting user input. while (Console.KeyAvailable) { Console.ReadKey(true); } } }