/// <summary> /// Prepares textmode to be used /// </summary> /// <param name="prompt"></param> /// <param name="onEnter">What happens when enter is pressed?</param> /// <param name="keydown">Custom keydown event. <see cref="Interactive.DefaultKeydown(string, ref string, ref int, ConsoleKeyInfo)"/> is used if no keydown is specified(null)</param> /// <param name="SpecialCaseHandler"></param> private void TextModeWrapper(string prompt, Action <string> onEnter, keydownAction keydown = null, Action <ConsoleKeyInfo> SpecialCaseHandler = null) { var tT = ""; getPromptText = () => prompt + tT; var typedIndex = 0; if (keydown == null) { keydown = DefaultKeydown; } onQueryModeKeyPress = (k) => TextInputMode(k, prompt, ref tT, ref typedIndex, onEnter, keydown, SpecialCaseHandler); }
/// <summary> /// Switches the input into Password mode. /// <para> /// This means typed characters won't be visible but instead substituted by <paramref name="disguiseChar"/>.</para> /// Passwords won't be stored in memory by the password mode, instead a <paramref name="storeChar"/> function /// has to be specified, which should store them safely and only as temporarily as possible. /// Adding the char to a <see cref="System.Security.SecureString"/> is a good implementation. /// </summary> /// <param name="prompt">current prompt</param> /// <param name="onEnter">What happens on enter press?</param> /// <param name="storeChar">Char storage function. Try to avoid <see cref="string"/>s</param> /// <param name="disguiseChar">the char to display instead of the actual character. defaults to *</param> /// <param name="keydown">Custom keydown event. A secure default implementation is used, if no custom keydown is specified(null)</param> /// <param name="SpecialCaseHandler"></param> private void PasswordModeWrapper(string prompt, Action <string> onEnter, Action <char> storeChar, char disguiseChar = '*', keydownAction keydown = null, Action <ConsoleKeyInfo> SpecialCaseHandler = null) { if (keydown == null) { keydown = (string p, ref string tT, ref int tI, ConsoleKeyInfo k) => { if (tI != tT.Length) { HideStr(p, tT); } tT = tT.Insert(tI, disguiseChar.ToString()); tI++; if (tI == tT.Length) { Console.Write(disguiseChar.ToString()); } else { Console.Write(tT); Console.CursorLeft = p.Length + tI; } storeChar?.Invoke(k.KeyChar); } } ; TextModeWrapper(prompt, onEnter, keydown, SpecialCaseHandler); }
/// <summary> /// TextInputMode is for accepting general text using the <see cref="keydownAction"/> delegate /// </summary> /// <param name="k">pressed key</param> /// <param name="prompt">current prompt</param> /// <param name="typedText">previously typed text</param> /// <param name="typedIndex">cursorindex</param> /// <param name="onEnter"></param> /// <param name="keydown">Custom keydown event</param> /// <param name="SpecialCaseHandler">Add Custom keyhandlers here. Will always be called</param> private static void TextInputMode(ConsoleKeyInfo k, string prompt, ref string typedText, ref int typedIndex, Action <string> onEnter, keydownAction keydown, Action <ConsoleKeyInfo> SpecialCaseHandler = null) { var ch = k.KeyChar; switch (k.Key) { case ConsoleKey.Enter: { onEnter(typedText); break; } case ConsoleKey.Backspace: if (typedText.Length != 0) { typedText = typedText.Remove(typedIndex - 1, 1); typedIndex--; if (typedIndex != typedText.Length) { HideStr(prompt, typedText); Console.Write(typedText); Console.CursorLeft = prompt.Length + typedIndex; } else { Console.Write(backspace); } } else { Beep(); } break; case ConsoleKey.Delete: if (typedIndex != typedText.Length && typedText.Length != 0) { typedText = typedText.Remove(typedIndex, 1); HideStr(prompt, typedText); Console.Write(typedText); Console.CursorLeft = prompt.Length + typedIndex; } else { Beep(); } break; case ConsoleKey.Escape: HideStr(prompt, typedText); typedText = ""; typedIndex = 0; break; case ConsoleKey.LeftArrow: if (typedIndex == 0) { Beep(); } else { typedIndex--; Console.CursorLeft = prompt.Length + typedIndex; } break; case ConsoleKey.RightArrow: if (typedIndex >= typedText.Length) { Beep(); } else { typedIndex++; Console.CursorLeft = prompt.Length + typedIndex; } break; default: keydown(prompt, ref typedText, ref typedIndex, k); break; } SpecialCaseHandler?.Invoke(k); }