protected IDisposable UseRequestedDispatchTables() { bool inViMode = PSConsoleReadLine.GetOptions().EditMode == EditMode.Vi; bool viModeParamPresent = MyInvocation.BoundParameters.ContainsKey("ViMode"); if (inViMode || viModeParamPresent) { if (!inViMode) { // "-ViMode" must have been specified explicitly. Well, okay... we can // modify the Vi tables... but isn't that an odd thing to do from // not-vi mode? WriteWarning(PSReadLineResources.NotInViMode); } if (ViMode == ViMode.Command) { return(PSConsoleReadLine.UseViCommandModeTables()); } else // default if -ViMode not specified, invalid, or "Insert" { return(PSConsoleReadLine.UseViInsertModeTables()); } } return(null); }
public void PossibleCompletionsPrompt() { TestSetup(KeyMode.Cmd, new KeyHandler("Ctrl+Spacebar", PSConsoleReadLine.PossibleCompletions)); PSConsoleReadLine.GetOptions().CompletionQueryItems = 10; _console.Clear(); Test("Get-Many", Keys( "Get-Many", _.CtrlSpace, CheckThat(() => AssertScreenIs(2, TokenClassification.Command, "Get-Many", NextLine, TokenClassification.None, "Display all 15 possibilities? (y or n) _")), "n")); _console.Clear(); Test("Get-Many", Keys( "Get-Many", _.CtrlSpace, CheckThat(() => AssertScreenIs(2, TokenClassification.Command, "Get-Many", NextLine, TokenClassification.None, "Display all 15 possibilities? (y or n) _")), "y", CheckThat(() => AssertScreenIs(4, TokenClassification.Command, "Get-Many", NextLine, TokenClassification.None, "Get-Many0 Get-Many3 Get-Many6 Get-Many9 Get-Many12", NextLine, "Get-Many1 Get-Many4 Get-Many7 Get-Many10 Get-Many13", NextLine, "Get-Many2 Get-Many5 Get-Many8 Get-Many11 Get-Many14")))); }
public void ShowTooltips() { TestSetup(KeyMode.Cmd, new KeyHandler("Ctrl+Spacebar", PSConsoleReadLine.PossibleCompletions)); PSConsoleReadLine.GetOptions().ShowToolTips = true; _console.Clear(); // TODO: }
public void TestShowTooltips() { TestSetup(KeyMode.Cmd); PSConsoleReadLine.GetOptions().ShowToolTips = true; Console.Clear(); Test("Get-Tooltips", Keys( "Get-Tooltips", _.CtrlSpace, CheckThat(() => AssertScreenIs(2, TokenClassification.Command, "Get-Tooltips", NextLine, TokenClassification.None, "item1 - useful description goes here")))); }
public void TestSearchHistory() { TestSetup(KeyMode.Cmd, new KeyHandler("UpArrow", PSConsoleReadLine.HistorySearchBackward), new KeyHandler("DownArrow", PSConsoleReadLine.HistorySearchForward)); // No history SetHistory(); Test("", Keys(_.UpArrow, _.DownArrow)); // Clear history in case the above added some history (but it shouldn't) SetHistory(); Test(" ", Keys(' ', _.UpArrow, _.DownArrow)); var options = PSConsoleReadLine.GetOptions(); var emphasisColors = Tuple.Create(options.EmphasisForegroundColor, options.EmphasisBackgroundColor); SetHistory("dosomething", "ps p*", "dir", "echo zzz"); Test("dosomething", Keys( "d", _.UpArrow, CheckThat(() => { AssertScreenIs(1, emphasisColors, 'd', TokenClassification.Command, "ir"); AssertCursorLeftIs(3); }), _.UpArrow, CheckThat(() => { AssertScreenIs(1, emphasisColors, 'd', TokenClassification.Command, "osomething"); AssertCursorLeftIs(11); }), _.DownArrow, CheckThat(() => { AssertScreenIs(1, emphasisColors, 'd', TokenClassification.Command, "ir"); AssertCursorLeftIs(3); }), _.UpArrow, CheckThat(() => { AssertScreenIs(1, emphasisColors, 'd', TokenClassification.Command, "osomething"); AssertCursorLeftIs(11); }))); }
public void TestHistorySearchCursorMovesToEnd() { TestSetup(KeyMode.Cmd, new KeyHandler("UpArrow", PSConsoleReadLine.HistorySearchBackward), new KeyHandler("DownArrow", PSConsoleReadLine.HistorySearchForward)); PSConsoleReadLine.SetOptions(new SetPSReadlineOption { HistorySearchCursorMovesToEnd = true }); var options = PSConsoleReadLine.GetOptions(); var emphasisColors = Tuple.Create(options.EmphasisForegroundColor, options.EmphasisBackgroundColor); SetHistory("dosomething", "ps p*", "dir", "echo zzz"); Test("dosomething", Keys( "d", _.UpArrow, CheckThat(() => { AssertScreenIs(1, emphasisColors, 'd', TokenClassification.Command, "ir"); AssertCursorLeftIs(3); }), _.UpArrow, CheckThat(() => { AssertScreenIs(1, emphasisColors, 'd', TokenClassification.Command, "osomething"); AssertCursorLeftIs(11); }), _.DownArrow, CheckThat(() => { AssertScreenIs(1, emphasisColors, 'd', TokenClassification.Command, "ir"); AssertCursorLeftIs(3); }), _.UpArrow, CheckThat(() => { AssertScreenIs(1, emphasisColors, 'd', TokenClassification.Command, "osomething"); AssertCursorLeftIs(11); }))); }
static void Main(string[] args) { var handle = GetStdHandle((uint)StandardHandleId.Output); GetConsoleMode(handle, out var mode); var vtEnabled = SetConsoleMode(handle, mode | ENABLE_VIRTUAL_TERMINAL_PROCESSING); var iss = InitialSessionState.CreateDefault2(); if (args.Any()) { iss.ImportPSModule(args[0]); } iss.ExecutionPolicy = ExecutionPolicy.Bypass; var rs = RunspaceFactory.CreateRunspace(iss); rs.Open(); Runspace.DefaultRunspace = rs; PSConsoleReadLine.SetOptions(new SetPSReadLineOption { HistoryNoDuplicates = false, PredictionViewStyle = PredictionViewStyle.ListView, PredictionSource = PredictionSource.HistoryAndPlugin, }); if (vtEnabled) { var options = PSConsoleReadLine.GetOptions(); options.CommandColor = "#8181f7"; options.StringColor = "\x1b[38;5;100m"; } using (var ps = PowerShell.Create(rs)) { var executionContext = ps.AddScript("$ExecutionContext").Invoke <EngineIntrinsics>().First(); // Detect if the read loop will enter VT input mode. var vtInputEnvVar = Environment.GetEnvironmentVariable("PSREADLINE_VTINPUT"); var stdin = GetStdHandle((uint)StandardHandleId.Input); GetConsoleMode(stdin, out var inputMode); if (vtInputEnvVar == "1" || (inputMode & ENABLE_VIRTUAL_TERMINAL_INPUT) != 0) { Console.WriteLine("\x1b[33mDefault input mode = virtual terminal\x1b[m"); } else { Console.WriteLine("\x1b[33mDefault input mode = Windows\x1b[m"); } // This is a workaround to ensure the command analysis cache has been created before // we enter into ReadLine. It's a little slow and infrequently needed, so just // uncomment if you hit a hang, run it once, then comment it out again. //ps.Commands.Clear(); //ps.AddCommand("Get-Command").Invoke(); executionContext.InvokeProvider.Item.Set("function:prompt", ScriptBlock.Create("'TestHostPS> '")); while (true) { ps.Commands.Clear(); Console.Write(string.Join("", ps.AddCommand("prompt").Invoke <string>())); var line = PSConsoleReadLine.ReadLine(rs, executionContext); Console.WriteLine(line); line = line.Trim().ToLower(); if (line.Equals("exit")) { Environment.Exit(0); } if (line.Equals("cmd")) { PSConsoleReadLine.SetOptions(new SetPSReadLineOption { EditMode = EditMode.Windows }); } if (line.Equals("emacs")) { PSConsoleReadLine.SetOptions(new SetPSReadLineOption { EditMode = EditMode.Emacs }); } if (line.Equals("vi")) { PSConsoleReadLine.SetOptions(new SetPSReadLineOption { EditMode = EditMode.Vi }); } if (line.Equals("nodupes")) { PSConsoleReadLine.SetOptions(new SetPSReadLineOption { HistoryNoDuplicates = true }); } if (line.Equals("vtinput")) { Environment.SetEnvironmentVariable("PSREADLINE_VTINPUT", "1"); } if (line.Equals("novtinput")) { Environment.SetEnvironmentVariable("PSREADLINE_VTINPUT", "0"); } if (line.Equals("listview")) { PSConsoleReadLine.SetOptions(new SetPSReadLineOption { PredictionViewStyle = PredictionViewStyle.ListView }); } if (line.Equals("inlineview")) { PSConsoleReadLine.SetOptions(new SetPSReadLineOption { PredictionViewStyle = PredictionViewStyle.InlineView }); } if (line.Equals("history")) { PSConsoleReadLine.SetOptions(new SetPSReadLineOption { PredictionSource = PredictionSource.History }); } if (line.Equals("plugin")) { PSConsoleReadLine.SetOptions(new SetPSReadLineOption { PredictionSource = PredictionSource.Plugin }); } if (line.Equals("historyplugin")) { PSConsoleReadLine.SetOptions(new SetPSReadLineOption { PredictionSource = PredictionSource.HistoryAndPlugin }); } if (line.StartsWith("import-module")) { ps.AddScript(line).Invoke(); } if (line.StartsWith("get-module")) { var modules = ps.AddScript(line).Invoke().ToList(); foreach (var m in modules) { Console.WriteLine(((PSModuleInfo)m.BaseObject).Name); } } } } }
static void Main() { var handle = GetStdHandle((uint)StandardHandleId.Output); GetConsoleMode(handle, out var mode); var vtEnabled = SetConsoleMode(handle, mode | ENABLE_VIRTUAL_TERMINAL_PROCESSING); var iss = InitialSessionState.CreateDefault2(); var rs = RunspaceFactory.CreateRunspace(iss); rs.Open(); Runspace.DefaultRunspace = rs; PSConsoleReadLine.SetOptions(new SetPSReadLineOption { EditMode = EditMode.Emacs, HistoryNoDuplicates = false, }); if (vtEnabled) { var options = PSConsoleReadLine.GetOptions(); options.CommandColor = "#8181f7"; options.StringColor = "\x1b[38;5;100m"; } PSConsoleReadLine.SetKeyHandler(new[] { "Ctrl+LeftArrow" }, PSConsoleReadLine.ShellBackwardWord, "ShellBackwardWord", ""); PSConsoleReadLine.SetKeyHandler(new[] { "Ctrl+RightArrow" }, PSConsoleReadLine.ShellNextWord, "ShellNextWord", ""); PSConsoleReadLine.SetKeyHandler(new[] { "F4" }, PSConsoleReadLine.HistorySearchBackward, "HistorySearchBackward", ""); PSConsoleReadLine.SetKeyHandler(new[] { "F5" }, PSConsoleReadLine.HistorySearchForward, "HistorySearchForward", ""); PSConsoleReadLine.SetKeyHandler(new[] { "Ctrl+d,Ctrl+c" }, PSConsoleReadLine.CaptureScreen, "CaptureScreen", ""); PSConsoleReadLine.SetKeyHandler(new[] { "Ctrl+d,Ctrl+p" }, PSConsoleReadLine.InvokePrompt, "InvokePrompt", ""); PSConsoleReadLine.SetKeyHandler(new[] { "Ctrl+d,Ctrl+x" }, CauseCrash, "CauseCrash", "Throw exception to test error handling"); PSConsoleReadLine.SetKeyHandler(new[] { "F6" }, PSConsoleReadLine.PreviousLine, "PreviousLine", ""); PSConsoleReadLine.SetKeyHandler(new[] { "F7" }, PSConsoleReadLine.NextLine, "NextLine", ""); PSConsoleReadLine.SetKeyHandler(new[] { "F2" }, PSConsoleReadLine.ValidateAndAcceptLine, "ValidateAndAcceptLine", ""); PSConsoleReadLine.SetKeyHandler(new[] { "Enter" }, PSConsoleReadLine.AcceptLine, "AcceptLine", ""); using (var ps = PowerShell.Create(RunspaceMode.CurrentRunspace)) { var executionContext = ps.AddScript("$ExecutionContext").Invoke <EngineIntrinsics>().First(); // Detect if the read loop will enter VT input mode. var vtInputEnvVar = Environment.GetEnvironmentVariable("PSREADLINE_VTINPUT"); var stdin = GetStdHandle((uint)StandardHandleId.Input); GetConsoleMode(stdin, out var inputMode); if (vtInputEnvVar == "1" || (inputMode & ENABLE_VIRTUAL_TERMINAL_INPUT) != 0) { Console.WriteLine("\x1b[33mDefault input mode = virtual terminal\x1b[m"); } else { Console.WriteLine("\x1b[33mDefault input mode = Windows\x1b[m"); } // This is a workaround to ensure the command analysis cache has been created before // we enter into ReadLine. It's a little slow and infrequently needed, so just // uncomment if you hit a hang, run it once, then comment it out again. //ps.Commands.Clear(); //ps.AddCommand("Get-Command").Invoke(); executionContext.InvokeProvider.Item.Set("function:prompt", ScriptBlock.Create("'TestHostPS> '")); while (true) { ps.Commands.Clear(); Console.Write(string.Join("", ps.AddCommand("prompt").Invoke <string>())); var line = PSConsoleReadLine.ReadLine(rs, executionContext); Console.WriteLine(line); line = line.Trim(); if (line.Equals("exit")) { Environment.Exit(0); } if (line.Equals("cmd")) { PSConsoleReadLine.SetOptions(new SetPSReadLineOption { EditMode = EditMode.Windows }); } if (line.Equals("emacs")) { PSConsoleReadLine.SetOptions(new SetPSReadLineOption { EditMode = EditMode.Emacs }); } if (line.Equals("vi")) { PSConsoleReadLine.SetOptions(new SetPSReadLineOption { EditMode = EditMode.Vi }); } if (line.Equals("nodupes")) { PSConsoleReadLine.SetOptions(new SetPSReadLineOption { HistoryNoDuplicates = true }); } if (line.Equals("vtinput")) { Environment.SetEnvironmentVariable("PSREADLINE_VTINPUT", "1"); } if (line.Equals("novtinput")) { Environment.SetEnvironmentVariable("PSREADLINE_VTINPUT", "0"); } } } }
protected override void EndProcessing() { WriteObject(PSConsoleReadLine.GetOptions()); }
static void Main() { var handle = GetStdHandle((uint)StandardHandleId.Output); uint mode; GetConsoleMode(handle, out mode); var b = SetConsoleMode(handle, mode | ENABLE_VIRTUAL_TERMINAL_PROCESSING); var iss = InitialSessionState.CreateDefault2(); var rs = RunspaceFactory.CreateRunspace(iss); rs.Open(); Runspace.DefaultRunspace = rs; PSConsoleReadLine.SetOptions(new SetPSReadlineOption { EditMode = EditMode.Emacs, HistoryNoDuplicates = true, }); var options = PSConsoleReadLine.GetOptions(); options.CommandColor = "#8181f7"; options.StringColor = "\x1b[38;5;100m"; PSConsoleReadLine.SetKeyHandler(new[] { "Ctrl+LeftArrow" }, PSConsoleReadLine.ShellBackwardWord, "", ""); PSConsoleReadLine.SetKeyHandler(new[] { "Ctrl+RightArrow" }, PSConsoleReadLine.ShellNextWord, "", ""); PSConsoleReadLine.SetKeyHandler(new[] { "F4" }, PSConsoleReadLine.HistorySearchBackward, "", ""); PSConsoleReadLine.SetKeyHandler(new[] { "F5" }, PSConsoleReadLine.HistorySearchForward, "", ""); PSConsoleReadLine.SetKeyHandler(new[] { "Ctrl+D,Ctrl+C" }, PSConsoleReadLine.CaptureScreen, "", ""); PSConsoleReadLine.SetKeyHandler(new[] { "Ctrl+D,Ctrl+P" }, PSConsoleReadLine.InvokePrompt, "", ""); PSConsoleReadLine.SetKeyHandler(new[] { "Ctrl+D,Ctrl+X" }, CauseCrash, "", ""); PSConsoleReadLine.SetKeyHandler(new[] { "F6" }, PSConsoleReadLine.PreviousLine, "", ""); PSConsoleReadLine.SetKeyHandler(new[] { "F7" }, PSConsoleReadLine.NextLine, "", ""); PSConsoleReadLine.SetKeyHandler(new[] { "F2" }, PSConsoleReadLine.ValidateAndAcceptLine, "", ""); PSConsoleReadLine.SetKeyHandler(new[] { "Enter" }, PSConsoleReadLine.AcceptLine, "", ""); EngineIntrinsics executionContext; using (var ps = PowerShell.Create(RunspaceMode.CurrentRunspace)) { executionContext = ps.AddScript("$ExecutionContext").Invoke <EngineIntrinsics>().FirstOrDefault(); // This is a workaround to ensure the command analysis cache has been created before // we enter into ReadLine. It's a little slow and infrequently needed, so just // uncomment if you hit a hang, run it once, then comment it out again. //ps.Commands.Clear(); //ps.AddCommand("Get-Command").Invoke(); executionContext.InvokeProvider.Item.Set("function:prompt", ScriptBlock.Create("'TestHostPS> '")); while (true) { ps.Commands.Clear(); Console.Write(string.Join("", ps.AddCommand("prompt").Invoke <string>())); var line = PSConsoleReadLine.ReadLine(rs, executionContext); Console.WriteLine(line); line = line.Trim(); if (line.Equals("exit")) { Environment.Exit(0); } if (line.Equals("cmd")) { PSConsoleReadLine.SetOptions(new SetPSReadlineOption { EditMode = EditMode.Windows }); } if (line.Equals("emacs")) { PSConsoleReadLine.SetOptions(new SetPSReadlineOption { EditMode = EditMode.Emacs }); } if (line.Equals("vi")) { PSConsoleReadLine.SetOptions(new SetPSReadlineOption { EditMode = EditMode.Vi }); } if (line.Equals("nodupes")) { PSConsoleReadLine.SetOptions(new SetPSReadlineOption { HistoryNoDuplicates = true }); } } } }
private static void EnableAnsiInput(ref ICharMap charMap) { charMap = new WindowsAnsiCharMap(PSConsoleReadLine.GetOptions().AnsiEscapeTimeout); }
public void TestInteractiveHistorySearch() { TestSetup(KeyMode.Emacs); SetHistory("echo aaa"); Test("echo aaa", Keys(_.CtrlR, 'a')); var options = PSConsoleReadLine.GetOptions(); var emphasisColors = Tuple.Create(options.EmphasisForegroundColor, options.EmphasisBackgroundColor); 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(_.CtrlR, '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(_.CtrlR, 'a', CheckThat(() => AssertScreenIs(2, TokenClassification.Command, "echo", TokenClassification.None, " ", emphasisColors, 'a', TokenClassification.None, "aa", NextLine, statusColors, "bck-i-search: a_")), _.CtrlR, CheckThat(() => AssertScreenIs(2, TokenClassification.Command, "echo", TokenClassification.None, " ", emphasisColors, 'a', TokenClassification.None, "bb", NextLine, statusColors, "bck-i-search: a_")), _.CtrlR, 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(_.CtrlR, '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", _.CtrlR, 'a', CheckThat(() => AssertScreenIs(2, TokenClassification.Command, "echo", TokenClassification.None, " ", emphasisColors, 'a', TokenClassification.None, "bc", NextLine, statusColors, "bck-i-search: a_")), _.CtrlG, CheckThat(() => AssertScreenIs(2, TokenClassification.Command, "echo", TokenClassification.None, " ", TokenClassification.None, "zed", NextLine)))); // Test that a random function terminates the search and has an // effect on the line found in history SetHistory("zz1", "echo abzz", "echo abc", "zz2"); Test("echo zed", Keys(_.CtrlR, 'a', CheckThat(() => AssertScreenIs(2, TokenClassification.Command, "echo", TokenClassification.None, " ", emphasisColors, 'a', TokenClassification.None, "bc", NextLine, statusColors, "bck-i-search: a_")), _.AltD, "zed")); // 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(_.CtrlR, '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(_.CtrlR, _.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(_.CtrlR, 'a', CheckThat(() => AssertScreenIs(2, TokenClassification.Command, "echo", TokenClassification.None, " ", emphasisColors, 'a', TokenClassification.None, "bc", NextLine, statusColors, "bck-i-search: a_")), _.CtrlR, CheckThat(() => AssertScreenIs(2, TokenClassification.Command, "echo", TokenClassification.None, " ", emphasisColors, 'a', TokenClassification.None, "bzz", NextLine, statusColors, "bck-i-search: a_")), _.CtrlR, CheckThat(() => AssertScreenIs(2, TokenClassification.Command, "echo", TokenClassification.None, " ", TokenClassification.None, "abzz", NextLine, statusColors, "failed-bck-i-search: a_")), _.CtrlS, CheckThat(() => AssertScreenIs(2, TokenClassification.Command, "echo", TokenClassification.None, " ", emphasisColors, 'a', TokenClassification.None, "bzz", NextLine, statusColors, "fwd-i-search: a_")), _.CtrlG)); // Test that searching works after a failed search SetHistory("echo aa1", "echo bb1", "echo bb2", "echo aa2"); Test("echo aa1", Keys(_.CtrlR, "zz", _.Backspace, _.Backspace, "a1", CheckThat(() => AssertScreenIs(2, TokenClassification.Command, "echo", TokenClassification.None, " a", emphasisColors, "a1", 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( _.CtrlR, "aa", CheckThat(() => AssertScreenIs(2, TokenClassification.Command, "echo", TokenClassification.None, " ", emphasisColors, "aa", TokenClassification.None, "2", NextLine, statusColors, "bck-i-search: aa_")), _.CtrlR, 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', _.CtrlR, 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 }
public void SensitiveHistoryDefaultBehavior() { TestSetup(KeyMode.Cmd); // No history SetHistory(); Test("", Keys(_.UpArrow, _.DownArrow)); var options = PSConsoleReadLine.GetOptions(); var oldHistoryFilePath = options.HistorySavePath; var oldHistorySaveStyle = options.HistorySaveStyle; // AddToHistoryHandler should be set to the default handler. Assert.Same(PSConsoleReadLineOptions.DefaultAddToHistoryHandler, options.AddToHistoryHandler); var newHistoryFilePath = Path.GetTempFileName(); var newHistorySaveStyle = HistorySaveStyle.SaveIncrementally; string[] expectedHistoryItems = new[] { "gcm c*", "ConvertTo-SecureString -AsPlainText -String abc -Force", "dir p*", "Publish-Module -NuGetApiKey abc", "ps c*", "mycommand -password abc", "echo foo", "cmd1 /token abc", "echo bar", "cmd2 --key abc", "echo zoo", "pki secret", "gcm p*" }; string[] expectedSavedItems = new[] { "gcm c*", "dir p*", "ps c*", "echo foo", "echo bar", "echo zoo", "gcm p*" }; try { options.HistorySavePath = newHistoryFilePath; options.HistorySaveStyle = newHistorySaveStyle; SetHistory(expectedHistoryItems); // Sensitive input history should be kept in the internal history queue. var historyItems = PSConsoleReadLine.GetHistoryItems(); Assert.Equal(expectedHistoryItems.Length, historyItems.Length); for (int i = 0; i < expectedHistoryItems.Length; i++) { Assert.Equal(expectedHistoryItems[i], historyItems[i].CommandLine); } // Sensitive input history should NOT be saved to the history file. string[] text = File.ReadAllLines(newHistoryFilePath); Assert.Equal(expectedSavedItems.Length, text.Length); for (int i = 0; i < text.Length; i++) { Assert.Equal(expectedSavedItems[i], text[i]); } } finally { options.HistorySavePath = oldHistoryFilePath; options.HistorySaveStyle = oldHistorySaveStyle; File.Delete(newHistoryFilePath); } }
public void SensitiveHistoryOptionalBehaviorWithScriptBlock() { TestSetup(KeyMode.Cmd); // No history SetHistory(); Test("", Keys(_.UpArrow, _.DownArrow)); var options = PSConsoleReadLine.GetOptions(); var oldHistoryFilePath = options.HistorySavePath; var oldHistorySaveStyle = options.HistorySaveStyle; // AddToHistoryHandler should be set to the default handler. Assert.Same(PSConsoleReadLineOptions.DefaultAddToHistoryHandler, options.AddToHistoryHandler); var newHistoryFilePath = Path.GetTempFileName(); var newHistorySaveStyle = HistorySaveStyle.SaveIncrementally; Func <string, object> newAddToHistoryHandler_ReturnBool = LanguagePrimitives.ConvertTo <Func <string, object> >( ScriptBlock.Create(@" param([string]$line) $line.Contains('gal')")); Func <string, object> newAddToHistoryHandler_ReturnEnum = LanguagePrimitives.ConvertTo <Func <string, object> >( ScriptBlock.Create(@" param([string]$line) if ($line.Contains('gal')) { [psobject]::AsPSObject([Microsoft.PowerShell.AddToHistoryOption]::MemoryOnly) } elseif ($line.Contains('gmo')) { 'SkipAdding' } else { [Microsoft.PowerShell.AddToHistoryOption]::MemoryAndFile }")); Func <string, object> newAddToHistoryHandler_ReturnOther = LanguagePrimitives.ConvertTo <Func <string, object> >( ScriptBlock.Create(@" param([string]$line) 'string value'")); string[] commandInputs = new[] { "gmo p*", "gcm c*", "gal dir", "ConvertTo-SecureString -AsPlainText -String abc -Force" }; string[] expectedQueuedItems = new[] { "gcm c*", "gal dir", "ConvertTo-SecureString -AsPlainText -String abc -Force" }; string[] expectedSavedItems = new[] { "gcm c*", "ConvertTo-SecureString -AsPlainText -String abc -Force" }; try { options.HistorySavePath = newHistoryFilePath; options.HistorySaveStyle = newHistorySaveStyle; // // Set null to the handler means we don't do the check. // options.AddToHistoryHandler = null; SetHistory(commandInputs); // All commands should be kept in the internal history queue. var historyItems = PSConsoleReadLine.GetHistoryItems(); Assert.Equal(commandInputs.Length, historyItems.Length); for (int i = 0; i < commandInputs.Length; i++) { Assert.Equal(commandInputs[i], historyItems[i].CommandLine); } // All commands are saved to the history file when 'ScrubSensitiveHistory' is set to 'false'. string[] text = File.ReadAllLines(newHistoryFilePath); Assert.Equal(commandInputs.Length, text.Length); for (int i = 0; i < text.Length; i++) { Assert.Equal(commandInputs[i], text[i]); } // // Use a handler that return boolean value. // true: Add to memory and file // false: Skip adding to history // options.AddToHistoryHandler = newAddToHistoryHandler_ReturnBool; // Clear the history file. File.WriteAllText(newHistoryFilePath, string.Empty); SetHistory(commandInputs); historyItems = PSConsoleReadLine.GetHistoryItems(); Assert.Single(historyItems); Assert.Equal("gal dir", historyItems[0].CommandLine); text = File.ReadAllLines(newHistoryFilePath); Assert.Single(text); Assert.Equal("gal dir", text[0]); // // Use a handler that return the expected enum type. // options.AddToHistoryHandler = newAddToHistoryHandler_ReturnEnum; File.WriteAllText(newHistoryFilePath, string.Empty); SetHistory(commandInputs); historyItems = PSConsoleReadLine.GetHistoryItems(); Assert.Equal(expectedQueuedItems.Length, historyItems.Length); for (int i = 0; i < expectedQueuedItems.Length; i++) { Assert.Equal(expectedQueuedItems[i], historyItems[i].CommandLine); } text = File.ReadAllLines(newHistoryFilePath); Assert.Equal(expectedSavedItems.Length, text.Length); for (int i = 0; i < text.Length; i++) { Assert.Equal(expectedSavedItems[i], text[i]); } // // Use a handler that return unexpected value. // - same behavior as setting the handler to null. // options.AddToHistoryHandler = newAddToHistoryHandler_ReturnOther; File.WriteAllText(newHistoryFilePath, string.Empty); SetHistory(commandInputs); historyItems = PSConsoleReadLine.GetHistoryItems(); Assert.Equal(commandInputs.Length, historyItems.Length); for (int i = 0; i < commandInputs.Length; i++) { Assert.Equal(commandInputs[i], historyItems[i].CommandLine); } // All commands are saved to the history file when 'ScrubSensitiveHistory' is set to 'false'. text = File.ReadAllLines(newHistoryFilePath); Assert.Equal(commandInputs.Length, text.Length); for (int i = 0; i < text.Length; i++) { Assert.Equal(commandInputs[i], text[i]); } } finally { options.HistorySavePath = oldHistoryFilePath; options.HistorySaveStyle = oldHistorySaveStyle; options.AddToHistoryHandler = PSConsoleReadLineOptions.DefaultAddToHistoryHandler; File.Delete(newHistoryFilePath); } }