From 5bbc26fb6691f14cab2d85940fdde905038b4089 Mon Sep 17 00:00:00 2001 From: Dave Tapley Date: Thu, 13 May 2021 15:26:46 -0700 Subject: [PATCH 1/2] Make Ctrl+R in Vi EditMode same as Windows (#2453) Existing functionality (ViSearchHistoryBackward, SearchForward) is already available via / and ? shortcuts. But ReverseSearchHistory and ForwardSearchHistory had no none. Also copied Ctrl+S and Ctrl+G since these had no conflicts in vi mode. Removed vi mode existing tests and copied (almost) verbatim from InteractiveHistorySearch to VIInteractiveHistorySearch. Omitted test which uses _.Alt_d from VIInteractiveHistorySearch since this is emacs specific. --- PSReadLine/KeyBindings.vi.cs | 9 +- test/HistoryTest.VI.cs | 247 +++++++++++++++++++++++++++++++---- 2 files changed, 224 insertions(+), 32 deletions(-) diff --git a/PSReadLine/KeyBindings.vi.cs b/PSReadLine/KeyBindings.vi.cs index 46cdc6068..5902f3247 100644 --- a/PSReadLine/KeyBindings.vi.cs +++ b/PSReadLine/KeyBindings.vi.cs @@ -86,8 +86,9 @@ private void SetDefaultViBindings() { Keys.F3, MakeKeyHandler(CharacterSearch, "CharacterSearch") }, { Keys.ShiftF3, MakeKeyHandler(CharacterSearchBackward,"CharacterSearchBackward") }, { Keys.CtrlAltQuestion, MakeKeyHandler(ShowKeyBindings, "ShowKeyBindings") }, - { Keys.CtrlR, MakeKeyHandler(ViSearchHistoryBackward,"ViSearchHistoryBackward") }, - { Keys.CtrlS, MakeKeyHandler(SearchForward, "SearchForward") }, + { Keys.CtrlR, MakeKeyHandler(ReverseSearchHistory, "ReverseSearchHistory") }, + { Keys.CtrlS, MakeKeyHandler(ForwardSearchHistory, "ForwardSearchHistory") }, + { Keys.CtrlG, MakeKeyHandler(Abort, "Abort") }, { Keys.AltH, MakeKeyHandler(ShowParameterHelp, "ShowParameterHelp") }, { Keys.F1, MakeKeyHandler(ShowCommandHelp, "ShowCommandHelp") }, }; @@ -202,9 +203,9 @@ private void SetDefaultViBindings() { Keys.Underbar, MakeKeyHandler(GotoFirstNonBlankOfLine, "GotoFirstNonBlankOfLine") }, { Keys.Tilde, MakeKeyHandler(InvertCase, "InvertCase") }, { Keys.Slash, MakeKeyHandler(ViSearchHistoryBackward, "ViSearchHistoryBackward") }, - { Keys.CtrlR, MakeKeyHandler(ViSearchHistoryBackward, "ViSearchHistoryBackward") }, + { Keys.CtrlR, MakeKeyHandler(ReverseSearchHistory, "ReverseSearchHistory") }, { Keys.Question, MakeKeyHandler(SearchForward, "SearchForward") }, - { Keys.CtrlS, MakeKeyHandler(SearchForward, "SearchForward") }, + { Keys.CtrlS, MakeKeyHandler(ForwardSearchHistory, "ForwardSearchHistory") }, { Keys.Plus, MakeKeyHandler(NextHistory, "NextHistory") }, { Keys.Minus, MakeKeyHandler(PreviousHistory, "PreviousHistory") }, { Keys.Period, MakeKeyHandler(RepeatLastCommand, "RepeatLastCommand") }, diff --git a/test/HistoryTest.VI.cs b/test/HistoryTest.VI.cs index 4ec4657e1..d9c5055d5 100644 --- a/test/HistoryTest.VI.cs +++ b/test/HistoryTest.VI.cs @@ -1,4 +1,5 @@ -using Microsoft.PowerShell; +using System; +using Microsoft.PowerShell; using Xunit; namespace Test @@ -50,39 +51,229 @@ public void ViHistory() } [SkippableFact] - public void ViSearchHistory() + public void ViInteractiveHistorySearch() { TestSetup(KeyMode.Vi); - // Clear history in case the above added some history (but it shouldn't) - SetHistory(); - Test( " ", Keys( ' ', _.UpArrow, _.DownArrow ) ); - - SetHistory( "dosomething", "this way", "that way", "anyway", "no way", "yah way" ); - - Test( "dosomething", Keys( - _.Escape, _.Slash, "some", _.Enter, CheckThat( () => AssertLineIs( "dosomething" ) ), - _.Question, "yah", _.Enter, CheckThat( () => AssertLineIs( "yah way" ) ), - _.Slash, "some", _.Enter, 'h' // need 'h' here to avoid bogus failure - ) ); - - SetHistory("dosomething", "this way", "that way", "anyway", "no way", "yah way"); - - Test("dosomething", Keys( - _.Escape, _.Ctrl_r, "some", _.Enter, CheckThat(() => AssertLineIs("dosomething")), - _.Ctrl_s, "yah", _.Enter, CheckThat(() => AssertLineIs("yah way")), - _.Ctrl_r, "some", _.Enter, 'h' // need 'h' here to avoid bogus failure + SetHistory("echo aaa"); + Test("echo aaa", Keys(_.Ctrl_r, 'a')); + + var emphasisColors = Tuple.Create(PSConsoleReadLineOptions.DefaultEmphasisColor, _console.BackgroundColor); + var statusColors = Tuple.Create(_console.ForegroundColor, _console.BackgroundColor); + + // Test entering multiple characters and the line is updated with new matches + SetHistory("zz1", "echo abc", "zz2", "echo abb", "zz3", "echo aaa", "zz4"); + Test("echo abc", Keys(_.Ctrl_r, + 'a', + CheckThat(() => AssertScreenIs(2, + TokenClassification.Command, "echo", + TokenClassification.None, " ", + emphasisColors, 'a', + TokenClassification.None, "aa", + NextLine, + statusColors, "bck-i-search: a_")), + 'b', CheckThat(() => AssertScreenIs(2, + TokenClassification.Command, "echo", + TokenClassification.None, " ", + emphasisColors, "ab", + TokenClassification.None, 'b', + NextLine, + statusColors, "bck-i-search: ab_")), + 'c', CheckThat(() => AssertScreenIs(2, + TokenClassification.Command, "echo", + TokenClassification.None, " ", + emphasisColors, "abc", + NextLine, + statusColors, "bck-i-search: abc_")))); + + // Test repeated Ctrl+r goes back through multiple matches + SetHistory("zz1", "echo abc", "zz2", "echo abb", "zz3", "echo aaa", "zz4"); + Test("echo abc", Keys(_.Ctrl_r, + 'a', + CheckThat(() => AssertScreenIs(2, + TokenClassification.Command, "echo", + TokenClassification.None, " ", + emphasisColors, 'a', + TokenClassification.None, "aa", + NextLine, + statusColors, "bck-i-search: a_")), + _.Ctrl_r, CheckThat(() => AssertScreenIs(2, + TokenClassification.Command, "echo", + TokenClassification.None, " ", + emphasisColors, 'a', + TokenClassification.None, "bb", + NextLine, + statusColors, "bck-i-search: a_")), + _.Ctrl_r, CheckThat(() => AssertScreenIs(2, + TokenClassification.Command, "echo", + TokenClassification.None, " ", + emphasisColors, 'a', + TokenClassification.None, "bc", + NextLine, + statusColors, "bck-i-search: a_")))); + + // Test that the current match doesn't change when typing + // additional characters, only emphasis should change. + SetHistory("zz1", "echo abzz", "echo abc", "zz2"); + Test("echo abc", Keys(_.Ctrl_r, + 'a', + CheckThat(() => AssertScreenIs(2, + TokenClassification.Command, "echo", + TokenClassification.None, " ", + emphasisColors, 'a', + TokenClassification.None, "bc", + NextLine, + statusColors, "bck-i-search: a_")), + 'b', + CheckThat(() => AssertScreenIs(2, + TokenClassification.Command, "echo", + TokenClassification.None, " ", + emphasisColors, "ab", + TokenClassification.None, 'c', + NextLine, + statusColors, "bck-i-search: ab_")))); + + // Test that abort restores line state before Ctrl+r + SetHistory("zz1", "echo abzz", "echo abc", "zz2"); + Test("echo zed", Keys("echo zed", _.Ctrl_r, + 'a', + CheckThat(() => AssertScreenIs(2, + TokenClassification.Command, "echo", + TokenClassification.None, " ", + emphasisColors, 'a', + TokenClassification.None, "bc", + NextLine, + statusColors, "bck-i-search: a_")), + _.Ctrl_g, + CheckThat(() => AssertScreenIs(2, + TokenClassification.Command, "echo", + TokenClassification.None, " ", + TokenClassification.None, "zed", + NextLine)))); + + // Test that Escape terminates the search leaving the + // cursor at the point in the match. + SetHistory("zz1", "echo abzz", "echo abc", "zz2"); + Test("echo yabc", Keys(_.Ctrl_r, + 'a', + CheckThat(() => AssertScreenIs(2, + TokenClassification.Command, "echo", + TokenClassification.None, " ", + emphasisColors, 'a', + TokenClassification.None, "bc", + NextLine, + statusColors, "bck-i-search: a_")), + _.Escape, "y")); + + // Test entering multiple characters, then backspace, make sure we restore + // the correct line + SetHistory("zz1", "echo abc", "zz2", "echo abb", "zz3", "echo aaa", "zz4"); + Test("echo aaa", Keys(_.Ctrl_r, + _.Backspace, // Try backspace on empty search string + "ab", CheckThat(() => AssertScreenIs(2, + TokenClassification.Command, "echo", + TokenClassification.None, " ", + emphasisColors, "ab", + TokenClassification.None, 'b', + NextLine, + statusColors, "bck-i-search: ab_")), + _.Backspace, + CheckThat(() => AssertScreenIs(2, + TokenClassification.Command, "echo", + TokenClassification.None, " ", + emphasisColors, 'a', + TokenClassification.None, "aa", + NextLine, + statusColors, "bck-i-search: a_")))); + + SetHistory("zz1", "echo abzz", "echo abc", "zz2"); + Test("", Keys(_.Ctrl_r, + 'a', + CheckThat(() => AssertScreenIs(2, + TokenClassification.Command, "echo", + TokenClassification.None, " ", + emphasisColors, 'a', + TokenClassification.None, "bc", + NextLine, + statusColors, "bck-i-search: a_")), + _.Ctrl_r, + CheckThat(() => AssertScreenIs(2, + TokenClassification.Command, "echo", + TokenClassification.None, " ", + emphasisColors, 'a', + TokenClassification.None, "bzz", + NextLine, + statusColors, "bck-i-search: a_")), + _.Ctrl_r, + CheckThat(() => AssertScreenIs(2, + TokenClassification.Command, "echo", + TokenClassification.None, " ", + TokenClassification.None, "abzz", + NextLine, + statusColors, "failed-bck-i-search: a_")), + _.Ctrl_s, + CheckThat(() => AssertScreenIs(2, + TokenClassification.Command, "echo", + TokenClassification.None, " ", + emphasisColors, 'a', + TokenClassification.None, "bzz", + NextLine, + statusColors, "fwd-i-search: a_")), + _.Ctrl_g)); + + // Test that searching works after a failed search + SetHistory("echo aa1", "echo bb1", "echo bb2", "echo aa2"); + Test("echo aa1", Keys(_.Ctrl_r, "zz", _.Backspace, _.Backspace, "a1", + CheckThat(() => AssertScreenIs(2, + TokenClassification.Command, "echo", + TokenClassification.None, " a", + emphasisColors, "a1", + NextLine, + statusColors, "bck-i-search: a1_")) )); - SetHistory("dosomething", "this way", "that way", "anyway", "no way", "yah way"); - - Test("dosomething", Keys( - _.Ctrl_r, "some", _.Enter, CheckThat(() => AssertLineIs("dosomething")), - _.Ctrl_s, "yah", _.Enter, CheckThat(() => AssertLineIs("yah way")), - _.Ctrl_r, "some", _.Enter, _.Escape // new esc here to avoid bogus failure - )); + // Test that searching works after backspace after a successful search + SetHistory("echo aa1", "echo bb1", "echo bb2", "echo aa2"); + Test("echo aa2", Keys( + _.Ctrl_r, + "aa", + CheckThat(() => AssertScreenIs(2, + TokenClassification.Command, "echo", + TokenClassification.None, " ", + emphasisColors, "aa", + TokenClassification.None, "2", + NextLine, + statusColors, "bck-i-search: aa_")), + _.Ctrl_r, + CheckThat(() => AssertScreenIs(2, + TokenClassification.Command, "echo", + TokenClassification.None, " ", + emphasisColors, "aa", + TokenClassification.None, "1", + NextLine, + statusColors, "bck-i-search: aa_")), + _.Backspace, + CheckThat(() => AssertScreenIs(2, + TokenClassification.Command, "echo", + TokenClassification.None, " ", + emphasisColors, "a", + TokenClassification.None, "a2", + NextLine, + statusColors, "bck-i-search: a_")), + 'a', _.Ctrl_r, + CheckThat(() => AssertScreenIs(2, + TokenClassification.Command, "echo", + TokenClassification.None, " ", + emphasisColors, "aa", + TokenClassification.None, "1", + NextLine, + statusColors, "bck-i-search: aa_")), + _.Backspace)); + + // TODO: long search line + // TODO: start with Ctrl+s + // TODO: "fast" typing in search where buffered keys after search is accepted } - [SkippableFact] public void ViHistoryRepeat() { From 5c005247e746ce10cd4ad02d502566cd280fca2c Mon Sep 17 00:00:00 2001 From: Dongbo Wang Date: Tue, 11 Jan 2022 16:47:49 -0800 Subject: [PATCH 2/2] Update the tests --- PSReadLine/KeyBindings.vi.cs | 5 +- test/HistoryTest.VI.cs | 265 +++++++++++------------------------ 2 files changed, 82 insertions(+), 188 deletions(-) diff --git a/PSReadLine/KeyBindings.vi.cs b/PSReadLine/KeyBindings.vi.cs index 5902f3247..e7498c166 100644 --- a/PSReadLine/KeyBindings.vi.cs +++ b/PSReadLine/KeyBindings.vi.cs @@ -202,10 +202,11 @@ private void SetDefaultViBindings() { Keys.Uphat, MakeKeyHandler(GotoFirstNonBlankOfLine, "GotoFirstNonBlankOfLine") }, { Keys.Underbar, MakeKeyHandler(GotoFirstNonBlankOfLine, "GotoFirstNonBlankOfLine") }, { Keys.Tilde, MakeKeyHandler(InvertCase, "InvertCase") }, - { Keys.Slash, MakeKeyHandler(ViSearchHistoryBackward, "ViSearchHistoryBackward") }, - { Keys.CtrlR, MakeKeyHandler(ReverseSearchHistory, "ReverseSearchHistory") }, + { Keys.Slash, MakeKeyHandler(ViSearchHistoryBackward, "ViSearchHistoryBackward") }, { Keys.Question, MakeKeyHandler(SearchForward, "SearchForward") }, + { Keys.CtrlR, MakeKeyHandler(ReverseSearchHistory, "ReverseSearchHistory") }, { Keys.CtrlS, MakeKeyHandler(ForwardSearchHistory, "ForwardSearchHistory") }, + { Keys.CtrlG, MakeKeyHandler(Abort, "Abort") }, { Keys.Plus, MakeKeyHandler(NextHistory, "NextHistory") }, { Keys.Minus, MakeKeyHandler(PreviousHistory, "PreviousHistory") }, { Keys.Period, MakeKeyHandler(RepeatLastCommand, "RepeatLastCommand") }, diff --git a/test/HistoryTest.VI.cs b/test/HistoryTest.VI.cs index d9c5055d5..5927ab9da 100644 --- a/test/HistoryTest.VI.cs +++ b/test/HistoryTest.VI.cs @@ -51,229 +51,122 @@ public void ViHistory() } [SkippableFact] - public void ViInteractiveHistorySearch() + public void ViSearchHistory() { TestSetup(KeyMode.Vi); - SetHistory("echo aaa"); - Test("echo aaa", Keys(_.Ctrl_r, 'a')); + // Clear history in case the above added some history (but it shouldn't) + SetHistory(); + Test(" ", Keys(' ', _.UpArrow, _.DownArrow)); var emphasisColors = Tuple.Create(PSConsoleReadLineOptions.DefaultEmphasisColor, _console.BackgroundColor); var statusColors = Tuple.Create(_console.ForegroundColor, _console.BackgroundColor); - // Test entering multiple characters and the line is updated with new matches - SetHistory("zz1", "echo abc", "zz2", "echo abb", "zz3", "echo aaa", "zz4"); - Test("echo abc", Keys(_.Ctrl_r, - 'a', - CheckThat(() => AssertScreenIs(2, - TokenClassification.Command, "echo", - TokenClassification.None, " ", - emphasisColors, 'a', - TokenClassification.None, "aa", - NextLine, - statusColors, "bck-i-search: a_")), - 'b', CheckThat(() => AssertScreenIs(2, - TokenClassification.Command, "echo", - TokenClassification.None, " ", - emphasisColors, "ab", - TokenClassification.None, 'b', - NextLine, - statusColors, "bck-i-search: ab_")), - 'c', CheckThat(() => AssertScreenIs(2, - TokenClassification.Command, "echo", - TokenClassification.None, " ", - emphasisColors, "abc", - NextLine, - statusColors, "bck-i-search: abc_")))); + SetHistory("dosomething", "this way", "that way", "anyway", "no way", "yah way"); - // Test repeated Ctrl+r goes back through multiple matches - SetHistory("zz1", "echo abc", "zz2", "echo abb", "zz3", "echo aaa", "zz4"); - Test("echo abc", Keys(_.Ctrl_r, - 'a', - CheckThat(() => AssertScreenIs(2, - TokenClassification.Command, "echo", - TokenClassification.None, " ", - emphasisColors, 'a', - TokenClassification.None, "aa", - NextLine, - statusColors, "bck-i-search: a_")), - _.Ctrl_r, CheckThat(() => AssertScreenIs(2, - TokenClassification.Command, "echo", - TokenClassification.None, " ", - emphasisColors, 'a', - TokenClassification.None, "bb", - NextLine, - statusColors, "bck-i-search: a_")), - _.Ctrl_r, CheckThat(() => AssertScreenIs(2, - TokenClassification.Command, "echo", - TokenClassification.None, " ", - emphasisColors, 'a', - TokenClassification.None, "bc", - NextLine, - statusColors, "bck-i-search: a_")))); + Test("dosomething", Keys( + _.Escape, _.Slash, "some", _.Enter, CheckThat(() => AssertLineIs("dosomething")), + _.Question, "yah", _.Enter, CheckThat(() => AssertLineIs("yah way")), + _.Slash, "some", _.Enter, 'h' // need 'h' here to avoid bogus failure + )); - // Test that the current match doesn't change when typing - // additional characters, only emphasis should change. - SetHistory("zz1", "echo abzz", "echo abc", "zz2"); - Test("echo abc", Keys(_.Ctrl_r, - 'a', - CheckThat(() => AssertScreenIs(2, - TokenClassification.Command, "echo", - TokenClassification.None, " ", - emphasisColors, 'a', - TokenClassification.None, "bc", - NextLine, - statusColors, "bck-i-search: a_")), - 'b', - CheckThat(() => AssertScreenIs(2, - TokenClassification.Command, "echo", - TokenClassification.None, " ", - emphasisColors, "ab", - TokenClassification.None, 'c', - NextLine, - statusColors, "bck-i-search: ab_")))); + SetHistory("someway", "noway", "yahway"); - // Test that abort restores line state before Ctrl+r - SetHistory("zz1", "echo abzz", "echo abc", "zz2"); - Test("echo zed", Keys("echo zed", _.Ctrl_r, - 'a', + Test("yahway", Keys( + // Change to Command mode. + _.Escape, + _.Ctrl_r, "way", CheckThat(() => AssertScreenIs(2, - TokenClassification.Command, "echo", - TokenClassification.None, " ", - emphasisColors, 'a', - TokenClassification.None, "bc", - NextLine, - statusColors, "bck-i-search: a_")), - _.Ctrl_g, - CheckThat(() => AssertScreenIs(2, - TokenClassification.Command, "echo", - TokenClassification.None, " ", - TokenClassification.None, "zed", - NextLine)))); - - // Test that Escape terminates the search leaving the - // cursor at the point in the match. - SetHistory("zz1", "echo abzz", "echo abc", "zz2"); - Test("echo yabc", Keys(_.Ctrl_r, - 'a', - CheckThat(() => AssertScreenIs(2, - TokenClassification.Command, "echo", - TokenClassification.None, " ", - emphasisColors, 'a', - TokenClassification.None, "bc", - NextLine, - statusColors, "bck-i-search: a_")), - _.Escape, "y")); - - // Test entering multiple characters, then backspace, make sure we restore - // the correct line - SetHistory("zz1", "echo abc", "zz2", "echo abb", "zz3", "echo aaa", "zz4"); - Test("echo aaa", Keys(_.Ctrl_r, - _.Backspace, // Try backspace on empty search string - "ab", CheckThat(() => AssertScreenIs(2, - TokenClassification.Command, "echo", - TokenClassification.None, " ", - emphasisColors, "ab", - TokenClassification.None, 'b', + TokenClassification.Command, "yah", + emphasisColors, "way", NextLine, - statusColors, "bck-i-search: ab_")), - _.Backspace, + statusColors, "bck-i-search: way_")), + _.Ctrl_r, CheckThat(() => AssertScreenIs(2, - TokenClassification.Command, "echo", - TokenClassification.None, " ", - emphasisColors, 'a', - TokenClassification.None, "aa", + TokenClassification.Command, "no", + emphasisColors, "way", NextLine, - statusColors, "bck-i-search: a_")))); - - SetHistory("zz1", "echo abzz", "echo abc", "zz2"); - Test("", Keys(_.Ctrl_r, - 'a', + statusColors, "bck-i-search: way_")), + _.Ctrl_r, CheckThat(() => AssertScreenIs(2, - TokenClassification.Command, "echo", - TokenClassification.None, " ", - emphasisColors, 'a', - TokenClassification.None, "bc", + TokenClassification.Command, "some", + emphasisColors, "way", NextLine, - statusColors, "bck-i-search: a_")), - _.Ctrl_r, + statusColors, "bck-i-search: way_")), + _.Ctrl_s, CheckThat(() => AssertScreenIs(2, - TokenClassification.Command, "echo", - TokenClassification.None, " ", - emphasisColors, 'a', - TokenClassification.None, "bzz", + TokenClassification.Command, "no", + emphasisColors, "way", NextLine, - statusColors, "bck-i-search: a_")), - _.Ctrl_r, + statusColors, "fwd-i-search: way_")), + _.Ctrl_s, CheckThat(() => AssertScreenIs(2, - TokenClassification.Command, "echo", - TokenClassification.None, " ", - TokenClassification.None, "abzz", + TokenClassification.Command, "yah", + emphasisColors, "way", NextLine, - statusColors, "failed-bck-i-search: a_")), + statusColors, "fwd-i-search: way_")), _.Ctrl_s, CheckThat(() => AssertScreenIs(2, - TokenClassification.Command, "echo", - TokenClassification.None, " ", - emphasisColors, 'a', - TokenClassification.None, "bzz", + TokenClassification.Command, "yahway", NextLine, - statusColors, "fwd-i-search: a_")), - _.Ctrl_g)); + statusColors, "failed-fwd-i-search: way_")), + + // Abort the history search. + _.Ctrl_g, CheckThat(() => AssertLineIs(string.Empty)), + // Search again and escape from the search. + _.Ctrl_r, "yah", + _.Escape, CheckThat(() => AssertScreenIs(1, TokenClassification.Command, "yahway")), + // We should not be able to edit the line, because we are in Command mode. + "nnn")); + + SetHistory("someway", "noway", "yahway"); - // Test that searching works after a failed search - SetHistory("echo aa1", "echo bb1", "echo bb2", "echo aa2"); - Test("echo aa1", Keys(_.Ctrl_r, "zz", _.Backspace, _.Backspace, "a1", + Test("nnnyahway", Keys( + _.Ctrl_r, "way", CheckThat(() => AssertScreenIs(2, - TokenClassification.Command, "echo", - TokenClassification.None, " a", - emphasisColors, "a1", + TokenClassification.Command, "yah", + emphasisColors, "way", NextLine, - statusColors, "bck-i-search: a1_")) - )); - - // Test that searching works after backspace after a successful search - SetHistory("echo aa1", "echo bb1", "echo bb2", "echo aa2"); - Test("echo aa2", Keys( + statusColors, "bck-i-search: way_")), _.Ctrl_r, - "aa", CheckThat(() => AssertScreenIs(2, - TokenClassification.Command, "echo", - TokenClassification.None, " ", - emphasisColors, "aa", - TokenClassification.None, "2", + TokenClassification.Command, "no", + emphasisColors, "way", NextLine, - statusColors, "bck-i-search: aa_")), + statusColors, "bck-i-search: way_")), _.Ctrl_r, CheckThat(() => AssertScreenIs(2, - TokenClassification.Command, "echo", - TokenClassification.None, " ", - emphasisColors, "aa", - TokenClassification.None, "1", + TokenClassification.Command, "some", + emphasisColors, "way", NextLine, - statusColors, "bck-i-search: aa_")), - _.Backspace, + statusColors, "bck-i-search: way_")), + _.Ctrl_s, CheckThat(() => AssertScreenIs(2, - TokenClassification.Command, "echo", - TokenClassification.None, " ", - emphasisColors, "a", - TokenClassification.None, "a2", + TokenClassification.Command, "no", + emphasisColors, "way", NextLine, - statusColors, "bck-i-search: a_")), - 'a', _.Ctrl_r, + statusColors, "fwd-i-search: way_")), + _.Ctrl_s, CheckThat(() => AssertScreenIs(2, - TokenClassification.Command, "echo", - TokenClassification.None, " ", - emphasisColors, "aa", - TokenClassification.None, "1", + TokenClassification.Command, "yah", + emphasisColors, "way", NextLine, - statusColors, "bck-i-search: aa_")), - _.Backspace)); - - // TODO: long search line - // TODO: start with Ctrl+s - // TODO: "fast" typing in search where buffered keys after search is accepted + statusColors, "fwd-i-search: way_")), + _.Ctrl_s, + CheckThat(() => AssertScreenIs(2, + TokenClassification.Command, "yahway", + NextLine, + statusColors, "failed-fwd-i-search: way_")), + + // Abort the history search. + _.Ctrl_g, CheckThat(() => AssertLineIs(string.Empty)), + // Search again and escape from the search. + _.Ctrl_r, "yah", + _.Escape, CheckThat(() => AssertScreenIs(1, TokenClassification.Command, "yahway")), + // We should be able to edit the line, because we are in Edit mode. + "nnn")); } + [SkippableFact] public void ViHistoryRepeat() {