/// <summary> /// Reads the line. /// </summary> /// <param name="text">The text.</param> /// <param name="style">The style.</param> /// <param name="inputRegex">The input regex.</param> /// <param name="hintColor">Color of the hint.</param> /// <returns></returns> public static string ReadLine(string text, PathSuggestionStyle style, string inputRegex = ".*", ConsoleColor hintColor = ConsoleColor.DarkGray) { if (!string.IsNullOrEmpty(text)) { Console.Write(text); } ConsoleKeyInfo input; var suggestion = string.Empty; var userInput = string.Empty; var readLine = string.Empty; string[] hintSource = null; int suggestionIndex = 0; // TODO: Check if userInput is a path and change behaviour between normal read line and this read line while (ConsoleKey.Enter != (input = Console.ReadKey()).Key) { if (input.Key == ConsoleKey.Backspace) { userInput = SimulateBackspace(userInput); // Update hints if the user input changed hintSource = UpdateHints(userInput, out suggestionIndex); } else if (input.Key == ConsoleKey.Tab && userInput.StartsWith("/")) { bool suggestionIsEmpty = string.IsNullOrEmpty(suggestion); // Load suggestions for current path if (suggestionIsEmpty) { hintSource = DisplayFolders(userInput, style); } if (hintSource?.Length > 1) { userInput = suggestion ?? userInput; } else if (hintSource?.Length == 1) { userInput = hintSource[0]; } if (!suggestionIsEmpty) { MustResetSuggestions(ref suggestion, ref suggestionIndex); } } else if (input.Key == ConsoleKey.UpArrow || input.Key == ConsoleKey.DownArrow) { bool isUp = input.Key == ConsoleKey.UpArrow; int nextIndex = hintSource.NavigateBounds(ref suggestionIndex, isUp); suggestion = hintSource?[nextIndex]; } else if (input.Key == ConsoleKey.LeftArrow || input.Key == ConsoleKey.RightArrow) { if (input.Key == ConsoleKey.LeftArrow) { userInput = SimulateBackspace(userInput); } else { userInput += suggestion[userInput.Length]; } // Update hints if the user input changed hintSource = UpdateHints(userInput, out suggestionIndex); } else if (input != default && Regex.IsMatch(input.KeyChar.ToString(), inputRegex)) { userInput += input.KeyChar; } if (string.IsNullOrEmpty(suggestion)) { suggestion = hintSource? .FirstOrDefault(item => item.Length > userInput.Length && item.Substring(0, userInput.Length) == userInput); } readLine = string.IsNullOrEmpty(suggestion) || userInput.Length > readLine.Length ? userInput : suggestion; ClearCurrentConsoleLine(); Console.Write(text + userInput); var originalColor = Console.ForegroundColor; Console.ForegroundColor = hintColor; if (userInput.Any()) { Console.Write(readLine.Substring(userInput.Length, readLine.Length - userInput.Length)); } Console.ForegroundColor = originalColor; } Console.WriteLine(readLine); return(userInput.Any() ? readLine : string.Empty); }
/// <summary> /// Displays the folders. /// </summary> /// <param name="path">The path.</param> /// <param name="style">The style.</param> /// <returns></returns> private static string[] DisplayFolders(string path, PathSuggestionStyle style = PathSuggestionStyle.Linux) { bool isWinStyle = GetStyle(path) == PathSuggestionStyle.Windows; bool isWinPlatform = Environment.OSVersion.Platform == PlatformID.Win32NT; char separator = isWinPlatform ? Path.DirectorySeparatorChar : Path.AltDirectorySeparatorChar; if (isWinPlatform) { path = ToWinDir(path); } if (string.IsNullOrEmpty(path)) { // Show drives var drives = DriveInfo.GetDrives() .Select(drive => isWinPlatform && style == PathSuggestionStyle.Linux ? ToUnixDir(drive.Name) : drive.Name) .ToArray(); drives.DrawAsTable(); return(drives); } string subfolder = path.Split(separator).Last().ToLowerInvariant(); bool isNeedle = false; if (!Directory.Exists(path)) { path = Path.GetDirectoryName(path); isNeedle = true; } var directories = !isNeedle ? Directory.GetDirectories(path) : Directory.GetDirectories(path) .Where(dir => dir.Split(separator).Last().ToLowerInvariant().StartsWith(subfolder)) .ToArray(); if (directories.Length >= 50) { Console.WriteLine(); Console.Write($"Display all {directories.Length} possibilities? (y or n)"); ConsoleKey key; do { key = Console.ReadKey().Key; // TODO: Don't display pressed key on console }while (!(key == ConsoleKey.Y || key == ConsoleKey.N)); if (key == ConsoleKey.N) { return(null); } } var dirs = directories.Select(dir => SanitizePath(dir, path)); if (dirs.Count() > 1) { dirs.DrawAsTable(); } if (!isWinStyle && isWinPlatform) { directories = directories .Select(ToUnixDir) .ToArray(); } return(directories); }