From 323815928228ed452f21dc738d0f3cadc841b1d5 Mon Sep 17 00:00:00 2001 From: Dongbo Wang Date: Mon, 10 Jan 2022 18:10:42 -0800 Subject: [PATCH] Make 'HistorySearchBackward' and 'HistorySearchForward' able to navigate the list view --- PSReadLine/History.cs | 9 ++ test/ListPredictionTest.cs | 205 ++++++++++++++++++++++++++++++++++++- 2 files changed, 212 insertions(+), 2 deletions(-) diff --git a/PSReadLine/History.cs b/PSReadLine/History.cs index 9c90ce503..637db8dd0 100644 --- a/PSReadLine/History.cs +++ b/PSReadLine/History.cs @@ -958,6 +958,11 @@ public static void HistorySearchBackward(ConsoleKeyInfo? key = null, object arg numericArg = -numericArg; } + if (UpdateListSelection(numericArg)) + { + return; + } + _singleton.SaveCurrentLine(); _singleton.HistorySearch(numericArg); } @@ -969,6 +974,10 @@ public static void HistorySearchBackward(ConsoleKeyInfo? key = null, object arg public static void HistorySearchForward(ConsoleKeyInfo? key = null, object arg = null) { TryGetArgAsInt(arg, out var numericArg, +1); + if (UpdateListSelection(numericArg)) + { + return; + } _singleton.SaveCurrentLine(); _singleton.HistorySearch(numericArg); diff --git a/test/ListPredictionTest.cs b/test/ListPredictionTest.cs index 7982ff1db..1a4ee2f9a 100644 --- a/test/ListPredictionTest.cs +++ b/test/ListPredictionTest.cs @@ -47,7 +47,7 @@ private void AssertDisplayedSuggestions(int count, Guid predictorId, uint sessio } [SkippableFact] - public void List_RenderSuggestion_NoMatching() + public void List_RenderSuggestion_NoMatching_DefaultUpArrowDownArrow() { TestSetup(KeyMode.Cmd); using var disp = SetPrediction(PredictionSource.History, PredictionViewStyle.ListView); @@ -64,6 +64,25 @@ public void List_RenderSuggestion_NoMatching() )); } + [SkippableFact] + public void List_RenderSuggestion_NoMatching_HistorySearchBackwardForward() + { + TestSetup(KeyMode.Cmd, + new KeyHandler("Ctrl+p", PSConsoleReadLine.HistorySearchBackward), + new KeyHandler("Ctrl+l", PSConsoleReadLine.HistorySearchForward)); + using var disp = SetPrediction(PredictionSource.History, PredictionViewStyle.ListView); + + // No matching history entry + SetHistory("echo -bar", "eca -zoo"); + Test(string.Empty, Keys( + _.Ctrl_p, CheckThat(() => AssertLineIs("eca -zoo")), + _.Ctrl_p, CheckThat(() => AssertLineIs("echo -bar")), + _.Ctrl_l, _.Ctrl_l, + CheckThat(() => AssertLineIs(string.Empty)), + CheckThat(() => AssertCursorLeftIs(0)) + )); + } + [SkippableFact] public void List_RenderSuggestion_ListUpdatesWhileTyping() { @@ -138,7 +157,7 @@ public void List_RenderSuggestion_ListUpdatesWhileTyping() } [SkippableFact] - public void List_RenderSuggestion_NavigateInList() + public void List_RenderSuggestion_NavigateInList_DefaultUpArrowDownArrow() { TestSetup(KeyMode.Cmd); int listWidth = CheckWindowSize(); @@ -317,6 +336,188 @@ public void List_RenderSuggestion_NavigateInList() )); } + [SkippableFact] + public void List_RenderSuggestion_NavigateInList_HistorySearchBackwardForward() + { + TestSetup(KeyMode.Cmd, + new KeyHandler("Ctrl+p", PSConsoleReadLine.HistorySearchBackward), + new KeyHandler("Ctrl+l", PSConsoleReadLine.HistorySearchForward)); + int listWidth = CheckWindowSize(); + var emphasisColors = Tuple.Create(PSConsoleReadLineOptions.DefaultEmphasisColor, _console.BackgroundColor); + using var disp = SetPrediction(PredictionSource.History, PredictionViewStyle.ListView); + + // Navigate up and down in the list + SetHistory("echo -bar", "eca -zoo"); + Test("e", Keys( + 'e', CheckThat(() => AssertScreenIs(3, + TokenClassification.Command, 'e', + NextLine, + TokenClassification.ListPrediction, '>', + TokenClassification.None, ' ', + emphasisColors, 'e', + TokenClassification.None, "ca -zoo", + TokenClassification.None, new string(' ', listWidth - 19), // 19 is the length of '> eca -zoo' plus '[History]'. + TokenClassification.None, '[', + TokenClassification.ListPrediction, "History", + TokenClassification.None, ']', + NextLine, + TokenClassification.ListPrediction, '>', + TokenClassification.None, ' ', + emphasisColors, 'e', + TokenClassification.None, "cho -bar", + TokenClassification.None, new string(' ', listWidth - 20), // 20 is the length of '> echo -bar' plus '[History]'. + TokenClassification.None, '[', + TokenClassification.ListPrediction, "History", + TokenClassification.None, ']' + )), + _.Ctrl_l, + CheckThat(() => AssertScreenIs(3, + TokenClassification.Command, "eca", + TokenClassification.None, ' ', + TokenClassification.Parameter, "-zoo", + NextLine, + TokenClassification.ListPrediction, '>', + TokenClassification.ListPredictionSelected, ' ', + emphasisColors, 'e', + TokenClassification.ListPredictionSelected, "ca -zoo", + TokenClassification.ListPredictionSelected, new string(' ', listWidth - 19), // 19 is the length of '> eca -zoo' plus '[History]'. + TokenClassification.ListPredictionSelected, '[', + TokenClassification.ListPrediction, "History", + TokenClassification.ListPredictionSelected, ']', + NextLine, + TokenClassification.ListPrediction, '>', + TokenClassification.None, ' ', + emphasisColors, 'e', + TokenClassification.None, "cho -bar", + TokenClassification.None, new string(' ', listWidth - 20), // 20 is the length of '> echo -bar' plus '[History]'. + TokenClassification.None, '[', + TokenClassification.ListPrediction, "History", + TokenClassification.None, ']' + )), + _.Ctrl_l, + CheckThat(() => AssertScreenIs(3, + TokenClassification.Command, "echo", + TokenClassification.None, ' ', + TokenClassification.Parameter, "-bar", + NextLine, + TokenClassification.ListPrediction, '>', + TokenClassification.None, ' ', + emphasisColors, 'e', + TokenClassification.None, "ca -zoo", + TokenClassification.None, new string(' ', listWidth - 19), // 19 is the length of '> eca -zoo' plus '[History]'. + TokenClassification.None, '[', + TokenClassification.ListPrediction, "History", + TokenClassification.None, ']', + NextLine, + TokenClassification.ListPrediction, '>', + TokenClassification.ListPredictionSelected, ' ', + emphasisColors, 'e', + TokenClassification.ListPredictionSelected, "cho -bar", + TokenClassification.ListPredictionSelected, new string(' ', listWidth - 20), // 20 is the length of '> echo -bar' plus '[History]'. + TokenClassification.ListPredictionSelected, '[', + TokenClassification.ListPrediction, "History", + TokenClassification.ListPredictionSelected, ']' + )), + _.Ctrl_l, + CheckThat(() => AssertScreenIs(3, + TokenClassification.Command, 'e', + NextLine, + TokenClassification.ListPrediction, '>', + TokenClassification.None, ' ', + emphasisColors, 'e', + TokenClassification.None, "ca -zoo", + TokenClassification.None, new string(' ', listWidth - 19), // 19 is the length of '> eca -zoo' plus '[History]'. + TokenClassification.None, '[', + TokenClassification.ListPrediction, "History", + TokenClassification.None, ']', + NextLine, + TokenClassification.ListPrediction, '>', + TokenClassification.None, ' ', + emphasisColors, 'e', + TokenClassification.None, "cho -bar", + TokenClassification.None, new string(' ', listWidth - 20), // 20 is the length of '> echo -bar' plus '[History]'. + TokenClassification.None, '[', + TokenClassification.ListPrediction, "History", + TokenClassification.None, ']' + )), + _.Ctrl_p, + CheckThat(() => AssertScreenIs(3, + TokenClassification.Command, "echo", + TokenClassification.None, ' ', + TokenClassification.Parameter, "-bar", + NextLine, + TokenClassification.ListPrediction, '>', + TokenClassification.None, ' ', + emphasisColors, 'e', + TokenClassification.None, "ca -zoo", + TokenClassification.None, new string(' ', listWidth - 19), // 19 is the length of '> eca -zoo' plus '[History]'. + TokenClassification.None, '[', + TokenClassification.ListPrediction, "History", + TokenClassification.None, ']', + NextLine, + TokenClassification.ListPrediction, '>', + TokenClassification.ListPredictionSelected, ' ', + emphasisColors, 'e', + TokenClassification.ListPredictionSelected, "cho -bar", + TokenClassification.ListPredictionSelected, new string(' ', listWidth - 20), // 20 is the length of '> echo -bar' plus '[History]'. + TokenClassification.ListPredictionSelected, '[', + TokenClassification.ListPrediction, "History", + TokenClassification.ListPredictionSelected, ']' + )), + _.Ctrl_p, + CheckThat(() => AssertScreenIs(3, + TokenClassification.Command, "eca", + TokenClassification.None, ' ', + TokenClassification.Parameter, "-zoo", + NextLine, + TokenClassification.ListPrediction, '>', + TokenClassification.ListPredictionSelected, ' ', + emphasisColors, 'e', + TokenClassification.ListPredictionSelected, "ca -zoo", + TokenClassification.ListPredictionSelected, new string(' ', listWidth - 19), // 19 is the length of '> eca -zoo' plus '[History]'. + TokenClassification.ListPredictionSelected, '[', + TokenClassification.ListPrediction, "History", + TokenClassification.ListPredictionSelected, ']', + NextLine, + TokenClassification.ListPrediction, '>', + TokenClassification.None, ' ', + emphasisColors, 'e', + TokenClassification.None, "cho -bar", + TokenClassification.None, new string(' ', listWidth - 20), // 20 is the length of '> echo -bar' plus '[History]'. + TokenClassification.None, '[', + TokenClassification.ListPrediction, "History", + TokenClassification.None, ']' + )), + _.Ctrl_p, + CheckThat(() => AssertScreenIs(3, + TokenClassification.Command, 'e', + NextLine, + TokenClassification.ListPrediction, '>', + TokenClassification.None, ' ', + emphasisColors, 'e', + TokenClassification.None, "ca -zoo", + TokenClassification.None, new string(' ', listWidth - 19), // 19 is the length of '> eca -zoo' plus '[History]'. + TokenClassification.None, '[', + TokenClassification.ListPrediction, "History", + TokenClassification.None, ']', + NextLine, + TokenClassification.ListPrediction, '>', + TokenClassification.None, ' ', + emphasisColors, 'e', + TokenClassification.None, "cho -bar", + TokenClassification.None, new string(' ', listWidth - 20), // 20 is the length of '> echo -bar' plus '[History]'. + TokenClassification.None, '[', + TokenClassification.ListPrediction, "History", + TokenClassification.None, ']' + )), + // Once accepted, the list should be cleared. + _.Enter, CheckThat(() => AssertScreenIs(2, + TokenClassification.Command, "e", + NextLine, + NextLine)) + )); + } + [SkippableFact] public void List_RenderSuggestion_Escape() {