/// <summary> /// Read string from console /// </summary> /// <param name="autocomplete">Autocomplete</param> /// <returns>Returns the readed string</returns> public string ReadFromConsole(IDictionary <string, List <ParameterInfo[]> > autocomplete = null) { // Write prompt _consoleWriter.Write(ReadPrompt, ConsoleOutputStyle.Prompt); // If have something loaded if (_manualInputs.Count > 0) { // Get first loaded command var input = _manualInputs[0]; _manualInputs.RemoveAt(0); if (!string.IsNullOrEmpty(input)) { // Print it _consoleWriter.WriteLine(input, ConsoleOutputStyle.Input); // Use it return(input); } } // Read from console string ret; if (autocomplete != null && autocomplete.Count > 0) { int cursor = 0; int historyIndex = 0; bool insertMode = true; var txt = new StringBuilder(); Console.CursorSize = !insertMode ? 100 : 25; _consoleWriter.GetCursorPosition(out int startX, out int startY); READ_LINE: var i = Console.ReadKey(true); switch (i.Key) { // Accept case ConsoleKey.Enter: { _consoleWriter.WriteLine("", ConsoleOutputStyle.Input); break; } // Remove case ConsoleKey.Delete: { if (cursor >= txt.Length) { goto READ_LINE; } txt.Remove(cursor, 1); if (txt.Length - cursor != 0) { _consoleWriter.SetCursorPosition(startX + cursor, startY); _consoleWriter.Write(txt.ToString().Substring(cursor) + " \b", ConsoleOutputStyle.Input); _consoleWriter.SetCursorPosition(startX + cursor, startY); } else { _consoleWriter.Write(" \b", ConsoleOutputStyle.Input); } goto READ_LINE; } case ConsoleKey.Backspace: { if (cursor > 0) { txt.Remove(cursor - 1, 1); cursor--; } else if (cursor == 0) { goto READ_LINE; } int l = txt.Length - cursor; if (l > 0) { _consoleWriter.Write("".PadLeft(l, ' '), ConsoleOutputStyle.Input); _consoleWriter.SetCursorPosition(startX + cursor, startY); _consoleWriter.Write(txt.ToString().Substring(cursor), ConsoleOutputStyle.Input); _consoleWriter.SetCursorPosition(startX + cursor, startY); } else { _consoleWriter.Write("\b \b", ConsoleOutputStyle.Input); } goto READ_LINE; } // Move case ConsoleKey.LeftArrow: case ConsoleKey.RightArrow: { if (i.Key == ConsoleKey.LeftArrow) { cursor = Math.Max(0, cursor - 1); } else { cursor = Math.Min(txt.Length, cursor + 1); } _consoleWriter.SetCursorPosition(startX + cursor, startY); goto READ_LINE; } case ConsoleKey.Home: case ConsoleKey.End: { if (i.Key != ConsoleKey.End) { cursor = 0; } else { cursor = txt.Length; } _consoleWriter.SetCursorPosition(startX + cursor, startY); goto READ_LINE; } // History case ConsoleKey.UpArrow: case ConsoleKey.PageUp: case ConsoleKey.DownArrow: case ConsoleKey.PageDown: { string strH = ""; if (_history.Count > 0) { historyIndex = (historyIndex + (i.Key == ConsoleKey.DownArrow || i.Key == ConsoleKey.PageDown ? 1 : -1)); if (historyIndex < 0) { historyIndex = _history.Count - 1; } else if (historyIndex > _history.Count - 1) { historyIndex = 0; } strH = _history[historyIndex]; txt.Clear(); txt.Append(strH); cursor = txt.Length; } CleanFromThisPoint(startX, startY); _consoleWriter.Write(strH, ConsoleOutputStyle.Input); goto READ_LINE; } // Autocomplete case ConsoleKey.Tab: { List <string> matches = new List <string>(); string cmd = txt.ToString().ToLowerInvariant(); foreach (KeyValuePair <string, List <ParameterInfo[]> > var in autocomplete) { if (!var.Key.StartsWith(cmd)) { continue; } matches.Add(var.Key); } if (matches.Count > 0) { int max = 0; if (matches.Count == 1) { // 1 found txt.Clear(); txt.Append(matches[0] + " "); cursor = txt.Length; max = matches[0].Length; } else { // Search match cmd = matches[0]; for (int x = 1, m = cmd.Length; x < m; x++) { bool ok = true; foreach (string s in matches) { if (s.StartsWith(cmd.Substring(0, x))) { continue; } ok = false; break; } if (ok) { max = x; } else { break; } } // Take coincidences txt.Clear(); txt.Append(matches[0].Substring(0, max)); cursor = txt.Length; } // Print found _consoleWriter.WriteLine("", ConsoleOutputStyle.Input); foreach (var var in matches) { _consoleWriter.Write(var.Substring(0, max), ConsoleOutputStyle.AutocompleteMatch); _consoleWriter.WriteLine(var.Substring(max), ConsoleOutputStyle.Autocomplete); } // Prompt _consoleWriter.Write(ReadPrompt, ConsoleOutputStyle.Prompt); _consoleWriter.GetCursorPosition(out startX, out startY); _consoleWriter.Write(txt.ToString(), ConsoleOutputStyle.Input); _consoleWriter.SetCursorPosition(startX + cursor, startY); } else { // No match _consoleWriter.WriteLine("", ConsoleOutputStyle.Input); } goto READ_LINE; } // Special case ConsoleKey.Insert: { insertMode = !insertMode; Console.CursorSize = !insertMode ? 100 : 25; goto READ_LINE; } // Write default: { txt.Insert(cursor, i.KeyChar); cursor++; if (!insertMode) { _consoleWriter.Write(i.KeyChar.ToString(), ConsoleOutputStyle.Input); if (cursor < txt.Length) { txt.Remove(cursor, 1); } } else { _consoleWriter.Write(txt.ToString().Substring(cursor - 1), ConsoleOutputStyle.Input); _consoleWriter.SetCursorPosition(startX + cursor, startY); } goto READ_LINE; } } ret = txt.ToString(); } else { _consoleWriter.ApplyStyle(ConsoleOutputStyle.Input); ret = Console.ReadLine(); } // Append to history if (_history.LastOrDefault() != ret) { if (_history.Count > MaxHistorySize) { _history.RemoveAt(0); } _history.Add(ret); } // return text return(ret); }