/// <summary> /// Reads input from user using hints. Commands history is supported. /// </summary> /// <param name="inputRegex"></param> /// <returns></returns> public string ReadLine(string inputRegex = ".*") { ConsoleKeyInfo input; _currentDirectory = Directory.GetCurrentDirectory(); var userInput = string.Empty; var fullInput = string.Empty; var wasUserInput = false; var length = string.IsNullOrEmpty(_options.InitialText) ? _currentDirectory.Length + ConsoleUtils.Prompt.Length : _options.InitialText.Length; var cursorPosition = new ConsoleCursorPosition(length, Console.CursorTop, Console.WindowWidth); ClearConsoleLinesAndWriteInitialText(cursorPosition.StartTop, cursorPosition.Top); Suggestion suggestion = InitialSuggestionAndHelp(cursorPosition.StartTop); while ((input = Console.ReadKey()).Key != ConsoleKey.Enter) { var writeSuggestionToConsole = false; int positionToDelete; if (_previousPressedKey == ConsoleKey.Tab && input.Key != ConsoleKey.Tab) { _suggestionsForUserInput = null; suggestion = null; } switch (input.Key) { case ConsoleKey.Delete: positionToDelete = cursorPosition.InputLength; if (positionToDelete >= 0 && positionToDelete < userInput.Length) { if (_currentDirectory.Length > cursorPosition.Left - cursorPosition.InputLength) { cursorPosition--; } userInput = userInput.Any() ? userInput.Remove(positionToDelete, 1) : string.Empty; } wasUserInput = !string.IsNullOrWhiteSpace(userInput); UpdateSuggestionsForUserInput(userInput); suggestion = GetFirstSuggestion(); break; case ConsoleKey.Backspace: positionToDelete = cursorPosition.InputLength - 1; if (positionToDelete >= 0 && positionToDelete < userInput.Length) { userInput = userInput.Any() ? userInput.Remove(positionToDelete, 1) : string.Empty; cursorPosition--; } if (cursorPosition.InputLength < 0) { cursorPosition = cursorPosition.SetLength(0); } wasUserInput = !string.IsNullOrWhiteSpace(userInput); UpdateSuggestionsForUserInput(userInput); suggestion = GetFirstSuggestion(); break; case ConsoleKey.Tab: if (_previousPressedKey == ConsoleKey.Tab) { suggestion = GetNextSuggestion(); if (suggestion != null) { writeSuggestionToConsole = true; userInput = suggestion.Value + ' '; } } else { if (suggestion != null) { writeSuggestionToConsole = true; userInput = suggestion.Value + ' '; ////UpdateSuggestionsForUserInput(userInput); suggestion = GetFirstSuggestion(); var tmp = fullInput.LastIndexOf(" "); if (fullInput.EndsWith("=")) { cursorPosition = cursorPosition.SetLength(fullInput.Length); } else if (tmp == -1) { cursorPosition = cursorPosition.SetLength(userInput.Length); } else { cursorPosition = cursorPosition.SetLength(tmp + userInput.Length); } } } break; case ConsoleKey.Spacebar: userInput = userInput.Insert(cursorPosition.InputLength, " "); wasUserInput = true; cursorPosition++; if (userInput.StartsWith(InternalTerminalCommands.Cd)) { UpdateDirectorySuggestionsForUserInput(userInput); suggestion = GetFirstSuggestion(); } else { _suggestionsForUserInput = null; suggestion = null; } break; case ConsoleKey.UpArrow: if (!wasUserInput) { userInput = GetPreviousCommandFromHistory(); cursorPosition = cursorPosition.SetLength(userInput.Length); } else { suggestion = GetPreviousSuggestion(); } break; case ConsoleKey.DownArrow: if (!wasUserInput) { userInput = GetNextCommandFromHistory(); cursorPosition = cursorPosition.SetLength(userInput.Length); } else { suggestion = GetNextSuggestion(); } break; case ConsoleKey.LeftArrow: if (cursorPosition.InputLength > 0) { cursorPosition--; } break; case ConsoleKey.RightArrow: if (cursorPosition.InputLength < userInput.Length) { cursorPosition++; } break; case ConsoleKey.Home: cursorPosition = cursorPosition.SetLength(0); break; case ConsoleKey.End: cursorPosition = cursorPosition.SetLength(userInput.Length); break; case ConsoleKey.F1: case ConsoleKey.F2: case ConsoleKey.F3: case ConsoleKey.F4: case ConsoleKey.F5: case ConsoleKey.F6: case ConsoleKey.F7: case ConsoleKey.F8: case ConsoleKey.F9: case ConsoleKey.F10: case ConsoleKey.F11: case ConsoleKey.F12: break; default: if (Regex.IsMatch(input.KeyChar.ToString(), inputRegex)) { cursorPosition++; userInput = userInput.Insert(cursorPosition.InputLength - 1, input.KeyChar.ToString()); } wasUserInput = true; if (userInput.StartsWith(InternalTerminalCommands.Cd) || _options.OnlyDirectoriesSuggestions) { UpdateDirectorySuggestionsForUserInput(userInput); } else { UpdateSuggestionsForUserInput(userInput); } suggestion = GetFirstSuggestion(); break; } ClearConsoleLinesAndWriteInitialText(cursorPosition.StartTop, cursorPosition.Top); var li = fullInput.TrimEnd().LastIndexOf(" "); if (li == -1 && !fullInput.StartsWith(InternalTerminalCommands.Cd, StringComparison.OrdinalIgnoreCase) && !_options.OnlyDirectoriesSuggestions) { if (input.Key == ConsoleKey.Tab && _previousPressedKey == ConsoleKey.Tab && suggestion != null) { fullInput = userInput; cursorPosition = cursorPosition.SetLength(fullInput.Length); ConsoleUtils.Write(fullInput, ConsoleColor.Green); } else { ConsoleUtils.Write(userInput, ConsoleColor.Green); fullInput = userInput; } } else { if (!writeSuggestionToConsole) { ConsoleUtils.Write(userInput, ConsoleColor.Green); fullInput = userInput; } else { userInput = WriteSugestionAsUserInput(userInput, suggestion, li, ref fullInput, ref cursorPosition); } } if (userInput.Any()) { if (suggestion != null && suggestion.Value != userInput && writeSuggestionToConsole == false) { WriteSuggestion(suggestion); WriteOnBottomLine(suggestion.Help); _lastSuggestion = suggestion; } else { var splitedUserInput = userInput.Split(' '); var toCheck = splitedUserInput.Last().Split('=').First(); if (_lastSuggestion != null && toCheck.Equals(_lastSuggestion.Value)) { WriteOnBottomLine(_lastSuggestion.Help); } else { WriteOnBottomLine(string.Empty); } } } else { WriteOnBottomLine(string.Empty); } Console.CursorLeft = cursorPosition.Left; Console.CursorTop = cursorPosition.Top; _previousPressedKey = input.Key; } Console.WriteLine(string.Empty); AddCommandToHistory(fullInput); return(fullInput); }
private string WriteSugestionAsUserInput(string userInput, Suggestion suggestion, int li, ref string fullInput, ref ConsoleCursorPosition cursorPosition) { var suggestionValue = userInput; suggestionValue = suggestionValue.TrimEnd(); if (li == -1) { li = fullInput.Length - 1; } bool startsWithCd = fullInput.StartsWith(InternalTerminalCommands.Cd, StringComparison.OrdinalIgnoreCase); if (!suggestionValue.StartsWith("-") && !startsWithCd && !_options.OnlyDirectoriesSuggestions) { suggestionValue = $" {suggestionValue} "; } else { if (fullInput.Contains(@"\") && startsWithCd) { var splitedInputs = fullInput.Split(' ').Last().Split('\\'); foreach (var spllitedInput in splitedInputs) { li = li + spllitedInput.Length + 1; } } else if (fullInput.Contains("/") && startsWithCd) { var splitedInputs = fullInput.Split(' ').Last().Split('/'); foreach (var spllitedInput in splitedInputs) { li = li + spllitedInput.Length + 1; } } else { if (suggestion.SuggestionType != HintType.DirectoryOrFile) { suggestionValue = $" {suggestionValue}"; } else if (startsWithCd) { li++; } else { if (fullInput.Contains("/") || fullInput.Contains(@"\")) { li++; } } } } if (suggestion.SuggestionType == HintType.Value) { suggestionValue = $" -{suggestion.Key}={suggestionValue.Trim()}"; } fullInput = $"{fullInput.Substring(0, li)}{suggestionValue}"; suggestionValue = fullInput; ConsoleUtils.Write(fullInput, ConsoleColor.Green); cursorPosition = cursorPosition.SetLength(fullInput.Length); return(suggestionValue); }
/// <summary> /// Reads input from user using hints. Commands history is supported /// </summary> /// <param name="inputRegex"></param> /// <param name="hintColor"></param> /// <returns></returns> public string ReadHintedLine(string inputRegex = ".*", ConsoleColor hintColor = ConsoleColor.DarkGray) { ConsoleKeyInfo input; Suggestion suggestion = null; var userInput = string.Empty; var fullInput = string.Empty; var readLine = string.Empty; var wasUserInput = false; var target = string.Empty; var cursorPosition = new ConsoleCursorPosition(ConsoleUtils.Prompt.Length, Console.CursorTop, Console.WindowWidth); ClearConsoleLines(cursorPosition.StartTop, cursorPosition.Top); while ((input = Console.ReadKey()).Key != ConsoleKey.Enter) { var writeSugestionToConsole = false; int positionToDelete; switch (input.Key) { case ConsoleKey.Delete: positionToDelete = cursorPosition.InputLength; if (positionToDelete >= 0 && positionToDelete < userInput.Length) { cursorPosition--; userInput = userInput.Any() ? userInput.Remove(positionToDelete, 1) : string.Empty; } wasUserInput = !string.IsNullOrWhiteSpace(userInput); UpdateSuggestionsForUserInput(userInput); suggestion = GetFirstSuggestion(); break; case ConsoleKey.Backspace: positionToDelete = cursorPosition.InputLength - 1; if (positionToDelete >= 0 && positionToDelete < userInput.Length) { userInput = userInput.Any() ? userInput.Remove(positionToDelete, 1) : string.Empty; cursorPosition--; } if (cursorPosition.InputLength < 0) { cursorPosition = cursorPosition.SetLength(0); } wasUserInput = !string.IsNullOrWhiteSpace(userInput); UpdateSuggestionsForUserInput(userInput); suggestion = GetFirstSuggestion(); break; case ConsoleKey.Tab: if (suggestion != null) { writeSugestionToConsole = true; userInput = suggestion.Value + ' '; UpdateSuggestionsForUserInput(userInput); suggestion = GetFirstSuggestion(); var tmp = fullInput.LastIndexOf(" "); if (tmp == -1) { cursorPosition = cursorPosition.SetLength(userInput.Length); } else { cursorPosition = cursorPosition.SetLength(tmp + userInput.Length); } } break; case ConsoleKey.Spacebar: userInput = userInput + " "; wasUserInput = true; cursorPosition++; ////if (suggestion != null) ////{ //// userInput = suggestion.Value + ' '; ////} ////else if (Regex.IsMatch(input.KeyChar.ToString(), inputRegex)) ////{ //// cursorPosition++; //// userInput = userInput.Insert(cursorPosition.InputLength - 1, input.KeyChar.ToString()); //// UpdateSuggestionsForUserInput(userInput); //// suggestion = GetFirstSuggestion(); //// cursorPosition = cursorPosition.SetLength(userInput.Length); ////} break; case ConsoleKey.UpArrow: if (!wasUserInput) { userInput = GetPreviousCommandFromHistory(); cursorPosition = cursorPosition.SetLength(userInput.Length); } else { suggestion = GetPreviousSuggestion(); } break; case ConsoleKey.DownArrow: if (!wasUserInput) { userInput = GetNextCommandFromHistory(); cursorPosition = cursorPosition.SetLength(userInput.Length); } else { suggestion = GetNextSuggestion(); } break; case ConsoleKey.LeftArrow: if (cursorPosition.InputLength > 0) { cursorPosition--; } break; case ConsoleKey.RightArrow: if (cursorPosition.InputLength < userInput.Length) { cursorPosition++; } break; case ConsoleKey.Home: cursorPosition = cursorPosition.SetLength(0); break; case ConsoleKey.End: cursorPosition = cursorPosition.SetLength(userInput.Length); break; case ConsoleKey.F1: case ConsoleKey.F2: case ConsoleKey.F3: case ConsoleKey.F4: case ConsoleKey.F5: case ConsoleKey.F6: case ConsoleKey.F7: case ConsoleKey.F8: case ConsoleKey.F9: case ConsoleKey.F10: case ConsoleKey.F11: case ConsoleKey.F12: break; default: if (Regex.IsMatch(input.KeyChar.ToString(), inputRegex)) { cursorPosition++; userInput = userInput.Insert(cursorPosition.InputLength - 1, input.KeyChar.ToString()); } wasUserInput = true; UpdateSuggestionsForUserInput(userInput); suggestion = GetFirstSuggestion(); break; } readLine = suggestion != null ? suggestion.Value : userInput.TrimEnd(' '); ClearConsoleLines(cursorPosition.StartTop, cursorPosition.Top); var li = fullInput.TrimEnd().LastIndexOf(" "); if (li == -1) { ConsoleUtils.Write(userInput, ConsoleColor.Green); fullInput = userInput; } else { if (!writeSugestionToConsole) { ConsoleUtils.Write(userInput, ConsoleColor.Green); fullInput = userInput; } else { userInput = userInput.TrimEnd(); if (!userInput.StartsWith("-")) { userInput = $"{userInput} "; } fullInput = $"{fullInput.Substring(0, li)} {userInput}"; userInput = fullInput; ConsoleUtils.Write(fullInput, ConsoleColor.Green); cursorPosition = cursorPosition.SetLength(fullInput.Length); } } if (userInput.Any()) { if (suggestion != null && suggestion.Value != userInput && writeSugestionToConsole == false) { WriteSuggestion(suggestion, hintColor); WriteOnBottomLine(suggestion.Help); } } Console.CursorLeft = cursorPosition.Left; Console.CursorTop = cursorPosition.Top; } //ClearConsoleLines(); Console.WriteLine(string.Empty); AddCommandToHistory(readLine); return(fullInput); }