diff --git a/src/Microsoft.PowerShell.Linux.Host/readline.cs b/src/Microsoft.PowerShell.Linux.Host/readline.cs index d8b3935aa0..d7e40dd202 100644 --- a/src/Microsoft.PowerShell.Linux.Host/readline.cs +++ b/src/Microsoft.PowerShell.Linux.Host/readline.cs @@ -229,16 +229,8 @@ namespace Microsoft.PowerShell.Linux.Host case ConsoleKey.F: this.OnRight(key.Modifiers); break; - case ConsoleKey.P: - // TODO: incremental search case ConsoleKey.R: - this.OnUpArrow(nested); - break; - case ConsoleKey.N: - // TODO: incremental search - case ConsoleKey.S: - this.OnDownArrow(nested); - break; + return this.ReverseSearch(nested, ref abort); case ConsoleKey.J: previousKeyPress = key; return true; @@ -572,6 +564,98 @@ namespace Microsoft.PowerShell.Linux.Host this.newHistory = false; } + /// + /// Reverse search through history + /// + private bool ReverseSearch(bool nested, ref bool abort) + { + GetHistory(nested); + + if (historyResult.Count == 0) + { + return false; + } + int searchPos = historyResult.Count - 1; + + StringBuilder searchString = new StringBuilder(); + string searchResult = String.Empty; + string failed = String.Empty; + + while (!abort) + { + OnEscape(); + Console.Out.Write("({0}reverse-i-search)'{1}':{2} ", failed, searchString.ToString(), searchResult); + + ConsoleKeyInfo key = Console.ReadKey(true); + + if (key.Modifiers.HasFlag(ConsoleModifiers.Control) && key.Key == ConsoleKey.R) + { + // do nothing + } + else if (key.Modifiers.HasFlag(ConsoleModifiers.Control) && key.Key == ConsoleKey.C) + { + Abort(); + return true; + } + else if (key.Key == ConsoleKey.Backspace) + { + if (searchString.Length > 0) + { + searchString.Length--; + } + searchPos = historyResult.Count - 1; + } + else if (key.Key == ConsoleKey.Enter) + { + BufferFromString(searchResult); + return true; + } + else if (((key.Key >= ConsoleKey.A && key.Key <= ConsoleKey.Z) + || (key.Key >= ConsoleKey.D0 && key.Key <= ConsoleKey.D9)) + && !key.Modifiers.HasFlag(ConsoleModifiers.Control) + && !key.Modifiers.HasFlag(ConsoleModifiers.Alt)) + { + searchString.Append(key.KeyChar); + } + else + { + OnEscape(); + BufferFromString(searchResult); + Render(); + return false; + } + + string result = searchHistory(searchString.ToString(), ref searchPos); + if (String.IsNullOrEmpty(result)) + { + failed = "failed "; + } + else + { + searchResult = result; + } + } + return false; // for compiler + } + + /// + /// Reverse search command history for one that match pattern + /// + private string searchHistory(string pattern, ref int pos) + { + for (int i = pos; i >= 0; --i) + { + string command = historyResult[i].Members["CommandLine"].Value.ToString(); + if (command.Contains(pattern)) + { + pos = i; + return command; + } + } + pos = -1; + return String.Empty; + } + /// /// Helper function to get command history ///