Files
Andy Jordan 06e3b4bcb6 Add fixture to enable existing tests for screen reader mode
Tests that depend on supported features such as menu completions, list
view, inline predictions, continuation prompt, and colors are skipped.

The "helper" module for running tests from the command-line and in
AppVeyor is minimally updated to not skip the new fixture.

A `BlankRestOfBuffer()` function implements the semantics of the `0J`
control sequence in the mock console.
2025-08-27 17:46:47 -07:00

1607 lines
85 KiB
C#

using System;
using System.Collections;
using System.Collections.ObjectModel;
using System.IO;
using System.Management.Automation;
using System.Reflection;
using Microsoft.PowerShell;
using Xunit;
namespace Test
{
public partial class ReadLine
{
[SkippableFact]
public void TabComplete()
{
TestSetup(KeyMode.Cmd);
Test("$true", Keys(
"$tr",
_.Tab,
CheckThat(() => AssertCursorLeftIs(5))));
// Validate no change on no match
Test("$zz", Keys(
"$zz",
_.Tab,
CheckThat(() => AssertCursorLeftIs(3))));
Test("$this", Keys(
"$t",
_.Tab,
CheckThat(() => AssertLineIs("$thing")),
_.Tab,
CheckThat(() => AssertLineIs("$this")),
_.Tab,
CheckThat(() => AssertLineIs("$true")),
_.Shift_Tab,
CheckThat(() => AssertLineIs("$this"))));
}
[SkippableFact]
public void InvalidCompletionResult()
{
TestSetup(KeyMode.Cmd);
for (int i = 1; i <= 4; i++)
{
var input = $"invalid result {i}";
Test(input, Keys(input, _.Tab));
}
}
[SkippableFact]
public void Complete()
{
TestSetup(KeyMode.Emacs);
Test("ambiguous1", Keys(
"ambig",
_.Tab,
CheckThat(() => AssertLineIs("ambiguous")),
'1'));
}
[SkippableFact]
public void PossibleCompletions()
{
TestSetup(KeyMode.Emacs);
_console.Clear();
// Test empty input, make sure line after the cursor is blank and cursor didn't move
Test("", Keys(
_.Alt_Equals,
CheckThat(() =>
{
AssertCursorLeftTopIs(0, 0);
AssertScreenIs(2, NextLine);
})));
const string promptLine1 = "c:\\windows";
const string promptLine2 = "PS> ";
using (var ps = PowerShell.Create(RunspaceMode.CurrentRunspace))
{
ps.AddScript($@"function prompt {{ ""{promptLine1}`n{promptLine2}"" }}");
ps.Invoke();
}
PSConsoleReadLine.SetOptions(new SetPSReadLineOption {ExtraPromptLineCount = 1});
_console.Clear();
Test("psvar", Keys(
"psvar",
_.Alt_Equals,
CheckThat(() => AssertScreenIs(5,
TokenClassification.None, promptLine1,
NextLine,
promptLine2,
TokenClassification.Command, "psvar",
NextLine,
"$pssomething",
NextLine,
TokenClassification.None, promptLine1,
NextLine,
promptLine2,
TokenClassification.Command, "psvar"))),
prompt: promptLine1 + "\n" + promptLine2);
using (var ps = PowerShell.Create(RunspaceMode.CurrentRunspace))
{
ps.AddCommand("Remove-Item").AddArgument("function:prompt");
ps.Invoke();
}
_console.Clear();
TestMustDing("none", Keys(
"none",
_.Alt_Equals,
CheckThat(() => AssertScreenIs(2, TokenClassification.Command, "none", NextLine))));
}
[SkippableFact]
public void PossibleCompletionsPrompt()
{
TestSetup(KeyMode.Cmd, new KeyHandler("Ctrl+Spacebar", PSConsoleReadLine.PossibleCompletions));
PSConsoleReadLine.GetOptions().CompletionQueryItems = 10;
_console.Clear();
Test("Get-Many", Keys(
"Get-Many", _.Ctrl_Spacebar,
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", _.Ctrl_Spacebar,
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"))));
}
[SkippableFact]
public void MenuCompletions_FilterByTyping()
{
TestSetup(KeyMode.Cmd, new KeyHandler("Ctrl+Spacebar", PSConsoleReadLine.MenuComplete));
_console.Clear();
Test("Get-Many4", Keys(
"Get-Many", _.Ctrl_Spacebar,
CheckThat(() => AssertScreenIs(4,
TokenClassification.Command, "Get-Many",
TokenClassification.Selection, "0", NextLine,
TokenClassification.Selection, "Get-Many0 ",
TokenClassification.None,
"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")),
"4",
CheckThat(() => AssertScreenIs(4,
TokenClassification.Command, "Get-Many4", NextLine,
TokenClassification.Selection, "Get-Many4 ", NextLine,
" ", NextLine,
" ", NextLine)),
_.Enter,
_.Enter
));
}
[SkippableFact]
public void MenuCompletions_Navigation1()
{
Skip.If(ScreenReaderModeEnabled, "Menu completions are not supported in screen reader mode.");
// Test 'RightArrow' and 'LeftArrow' with the following menu:
// Get-Many0 Get-Many3 Get-Many6 Get-Many9 Get-Many12
// Get-Many1 Get-Many4 Get-Many7 Get-Many10 Get-Many13
// Get-Many2 Get-Many5 Get-Many8 Get-Many11 Get-Many14
TestSetup(KeyMode.Cmd, new KeyHandler("Ctrl+Spacebar", PSConsoleReadLine.MenuComplete));
_console.Clear();
Test("Get-Many0", Keys(
"Get-Many", _.Ctrl_Spacebar,
CheckThat(() => AssertScreenIs(4,
TokenClassification.Command, "Get-Many",
TokenClassification.Selection, "0", NextLine,
TokenClassification.Selection, "Get-Many0 ",
TokenClassification.None,
"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")),
_.RightArrow,
CheckThat(() => AssertScreenIs(4,
TokenClassification.Command, "Get-Many",
TokenClassification.Selection, "3", NextLine,
TokenClassification.None, "Get-Many0 ",
TokenClassification.Selection, "Get-Many3 ",
TokenClassification.None,
"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")),
_.RightArrow,
CheckThat(() => AssertScreenIs(4,
TokenClassification.Command, "Get-Many",
TokenClassification.Selection, "6", NextLine,
TokenClassification.None, "Get-Many0 Get-Many3 ",
TokenClassification.Selection, "Get-Many6 ",
TokenClassification.None, "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")),
_.RightArrow,
CheckThat(() => AssertScreenIs(4,
TokenClassification.Command, "Get-Many",
TokenClassification.Selection, "9", NextLine,
TokenClassification.None, "Get-Many0 Get-Many3 Get-Many6 ",
TokenClassification.Selection, "Get-Many9 ",
TokenClassification.None, "Get-Many12", NextLine,
"Get-Many1 Get-Many4 Get-Many7 Get-Many10 Get-Many13", NextLine,
"Get-Many2 Get-Many5 Get-Many8 Get-Many11 Get-Many14")),
_.RightArrow,
CheckThat(() => AssertScreenIs(4,
TokenClassification.Command, "Get-Many",
TokenClassification.Selection, "12", NextLine,
TokenClassification.None, "Get-Many0 Get-Many3 Get-Many6 Get-Many9 ",
TokenClassification.Selection, "Get-Many12 ", NextLine,
TokenClassification.None,
"Get-Many1 Get-Many4 Get-Many7 Get-Many10 Get-Many13", NextLine,
"Get-Many2 Get-Many5 Get-Many8 Get-Many11 Get-Many14")),
_.RightArrow,
CheckThat(() => AssertScreenIs(4,
TokenClassification.Command, "Get-Many",
TokenClassification.Selection, "1", NextLine,
TokenClassification.None,
"Get-Many0 Get-Many3 Get-Many6 Get-Many9 Get-Many12", NextLine,
TokenClassification.Selection, "Get-Many1 ",
TokenClassification.None,
"Get-Many4 Get-Many7 Get-Many10 Get-Many13", NextLine,
"Get-Many2 Get-Many5 Get-Many8 Get-Many11 Get-Many14")),
_.LeftArrow,
CheckThat(() => AssertScreenIs(4,
TokenClassification.Command, "Get-Many",
TokenClassification.Selection, "12", NextLine,
TokenClassification.None, "Get-Many0 Get-Many3 Get-Many6 Get-Many9 ",
TokenClassification.Selection, "Get-Many12 ", NextLine,
TokenClassification.None,
"Get-Many1 Get-Many4 Get-Many7 Get-Many10 Get-Many13", NextLine,
"Get-Many2 Get-Many5 Get-Many8 Get-Many11 Get-Many14")),
_.LeftArrow,
CheckThat(() => AssertScreenIs(4,
TokenClassification.Command, "Get-Many",
TokenClassification.Selection, "9", NextLine,
TokenClassification.None, "Get-Many0 Get-Many3 Get-Many6 ",
TokenClassification.Selection, "Get-Many9 ",
TokenClassification.None, "Get-Many12", NextLine,
"Get-Many1 Get-Many4 Get-Many7 Get-Many10 Get-Many13", NextLine,
"Get-Many2 Get-Many5 Get-Many8 Get-Many11 Get-Many14")),
_.LeftArrow,
CheckThat(() => AssertScreenIs(4,
TokenClassification.Command, "Get-Many",
TokenClassification.Selection, "6", NextLine,
TokenClassification.None, "Get-Many0 Get-Many3 ",
TokenClassification.Selection, "Get-Many6 ",
TokenClassification.None, "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")),
_.LeftArrow, _.LeftArrow,
CheckThat(() => AssertScreenIs(4,
TokenClassification.Command, "Get-Many",
TokenClassification.Selection, "0", NextLine,
TokenClassification.Selection, "Get-Many0 ",
TokenClassification.None,
"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")),
_.LeftArrow,
CheckThat(() => AssertScreenIs(4,
TokenClassification.Command, "Get-Many",
TokenClassification.Selection, "14", 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 ",
TokenClassification.Selection, "Get-Many14 ", NextLine)),
_.RightArrow,
CheckThat(() => AssertScreenIs(4,
TokenClassification.Command, "Get-Many",
TokenClassification.Selection, "0", NextLine,
TokenClassification.Selection, "Get-Many0 ",
TokenClassification.None,
"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")),
_.Enter,
_.Enter
));
}
[SkippableFact]
public void MenuCompletions_Navigation2()
{
Skip.If(ScreenReaderModeEnabled, "Menu completions are not supported in screen reader mode.");
// Test 'RightArrow' with the following menu:
// Get-Less0 Get-Less3 Get-Less6 Get-Less9 Get-Less12
// Get-Less1 Get-Less4 Get-Less7 Get-Less10
// Get-Less2 Get-Less5 Get-Less8 Get-Less11
TestSetup(KeyMode.Cmd, new KeyHandler("Ctrl+Spacebar", PSConsoleReadLine.MenuComplete));
_console.Clear();
Test("Get-Less0", Keys(
"Get-Less", _.Ctrl_Spacebar,
CheckThat(() => AssertScreenIs(4,
TokenClassification.Command, "Get-Less",
TokenClassification.Selection, "0", NextLine,
TokenClassification.Selection, "Get-Less0 ",
TokenClassification.None,
"Get-Less3 Get-Less6 Get-Less9 Get-Less12", NextLine,
"Get-Less1 Get-Less4 Get-Less7 Get-Less10", NextLine,
"Get-Less2 Get-Less5 Get-Less8 Get-Less11")),
_.RightArrow, _.RightArrow, _.RightArrow, _.RightArrow,
CheckThat(() => AssertScreenIs(4,
TokenClassification.Command, "Get-Less",
TokenClassification.Selection, "12", NextLine,
TokenClassification.None, "Get-Less0 Get-Less3 Get-Less6 Get-Less9 ",
TokenClassification.Selection, "Get-Less12 ", NextLine,
TokenClassification.None,
"Get-Less1 Get-Less4 Get-Less7 Get-Less10", NextLine,
"Get-Less2 Get-Less5 Get-Less8 Get-Less11")),
_.RightArrow,
CheckThat(() => AssertScreenIs(4,
TokenClassification.Command, "Get-Less",
TokenClassification.Selection, "1", NextLine,
TokenClassification.None,
"Get-Less0 Get-Less3 Get-Less6 Get-Less9 Get-Less12", NextLine,
TokenClassification.Selection, "Get-Less1 ",
TokenClassification.None,
"Get-Less4 Get-Less7 Get-Less10", NextLine,
"Get-Less2 Get-Less5 Get-Less8 Get-Less11")),
_.RightArrow, _.RightArrow, _.RightArrow,
CheckThat(() => AssertScreenIs(4,
TokenClassification.Command, "Get-Less",
TokenClassification.Selection, "10", NextLine,
TokenClassification.None,
"Get-Less0 Get-Less3 Get-Less6 Get-Less9 Get-Less12", NextLine,
"Get-Less1 Get-Less4 Get-Less7 ",
TokenClassification.Selection, "Get-Less10 ", NextLine,
TokenClassification.None,
"Get-Less2 Get-Less5 Get-Less8 Get-Less11")),
_.RightArrow,
CheckThat(() => AssertScreenIs(4,
TokenClassification.Command, "Get-Less",
TokenClassification.Selection, "2", NextLine,
TokenClassification.None,
"Get-Less0 Get-Less3 Get-Less6 Get-Less9 Get-Less12", NextLine,
"Get-Less1 Get-Less4 Get-Less7 Get-Less10", NextLine,
TokenClassification.Selection, "Get-Less2 ",
TokenClassification.None,
"Get-Less5 Get-Less8 Get-Less11")),
_.RightArrow, _.RightArrow, _.RightArrow,
CheckThat(() => AssertScreenIs(4,
TokenClassification.Command, "Get-Less",
TokenClassification.Selection, "11", NextLine,
TokenClassification.None,
"Get-Less0 Get-Less3 Get-Less6 Get-Less9 Get-Less12", NextLine,
"Get-Less1 Get-Less4 Get-Less7 Get-Less10", NextLine,
"Get-Less2 Get-Less5 Get-Less8 ",
TokenClassification.Selection, "Get-Less11 ")),
_.RightArrow,
CheckThat(() => AssertScreenIs(4,
TokenClassification.Command, "Get-Less",
TokenClassification.Selection, "0", NextLine,
TokenClassification.Selection, "Get-Less0 ",
TokenClassification.None,
"Get-Less3 Get-Less6 Get-Less9 Get-Less12", NextLine,
"Get-Less1 Get-Less4 Get-Less7 Get-Less10", NextLine,
"Get-Less2 Get-Less5 Get-Less8 Get-Less11")),
_.Enter,
_.Enter
));
}
[SkippableFact]
public void MenuCompletions_Navigation3()
{
Skip.If(ScreenReaderModeEnabled, "Menu completions are not supported in screen reader mode.");
// Test 'LeftArrow' with the following menu:
// Get-Less0 Get-Less3 Get-Less6 Get-Less9 Get-Less12
// Get-Less1 Get-Less4 Get-Less7 Get-Less10
// Get-Less2 Get-Less5 Get-Less8 Get-Less11
TestSetup(KeyMode.Cmd, new KeyHandler("Ctrl+Spacebar", PSConsoleReadLine.MenuComplete));
_console.Clear();
Test("Get-Less6", Keys(
"Get-Less", _.Ctrl_Spacebar,
CheckThat(() => AssertScreenIs(4,
TokenClassification.Command, "Get-Less",
TokenClassification.Selection, "0", NextLine,
TokenClassification.Selection, "Get-Less0 ",
TokenClassification.None,
"Get-Less3 Get-Less6 Get-Less9 Get-Less12", NextLine,
"Get-Less1 Get-Less4 Get-Less7 Get-Less10", NextLine,
"Get-Less2 Get-Less5 Get-Less8 Get-Less11")),
_.LeftArrow,
CheckThat(() => AssertScreenIs(4,
TokenClassification.Command, "Get-Less",
TokenClassification.Selection, "11", NextLine,
TokenClassification.None,
"Get-Less0 Get-Less3 Get-Less6 Get-Less9 Get-Less12", NextLine,
"Get-Less1 Get-Less4 Get-Less7 Get-Less10", NextLine,
"Get-Less2 Get-Less5 Get-Less8 ",
TokenClassification.Selection, "Get-Less11 ")),
_.LeftArrow, _.LeftArrow, _.LeftArrow,
CheckThat(() => AssertScreenIs(4,
TokenClassification.Command, "Get-Less",
TokenClassification.Selection, "2", NextLine,
TokenClassification.None,
"Get-Less0 Get-Less3 Get-Less6 Get-Less9 Get-Less12", NextLine,
"Get-Less1 Get-Less4 Get-Less7 Get-Less10", NextLine,
TokenClassification.Selection, "Get-Less2 ",
TokenClassification.None,
"Get-Less5 Get-Less8 Get-Less11")),
_.LeftArrow,
CheckThat(() => AssertScreenIs(4,
TokenClassification.Command, "Get-Less",
TokenClassification.Selection, "10", NextLine,
TokenClassification.None,
"Get-Less0 Get-Less3 Get-Less6 Get-Less9 Get-Less12", NextLine,
"Get-Less1 Get-Less4 Get-Less7 ",
TokenClassification.Selection, "Get-Less10 ", NextLine,
TokenClassification.None,
"Get-Less2 Get-Less5 Get-Less8 Get-Less11")),
_.LeftArrow, _.LeftArrow, _.LeftArrow,
CheckThat(() => AssertScreenIs(4,
TokenClassification.Command, "Get-Less",
TokenClassification.Selection, "1", NextLine,
TokenClassification.None,
"Get-Less0 Get-Less3 Get-Less6 Get-Less9 Get-Less12", NextLine,
TokenClassification.Selection, "Get-Less1 ",
TokenClassification.None,
"Get-Less4 Get-Less7 Get-Less10", NextLine,
"Get-Less2 Get-Less5 Get-Less8 Get-Less11")),
_.LeftArrow,
CheckThat(() => AssertScreenIs(4,
TokenClassification.Command, "Get-Less",
TokenClassification.Selection, "12", NextLine,
TokenClassification.None, "Get-Less0 Get-Less3 Get-Less6 Get-Less9 ",
TokenClassification.Selection, "Get-Less12 ", NextLine,
TokenClassification.None,
"Get-Less1 Get-Less4 Get-Less7 Get-Less10", NextLine,
"Get-Less2 Get-Less5 Get-Less8 Get-Less11")),
_.LeftArrow, _.LeftArrow,
_.Enter,
_.Enter
));
}
[SkippableFact]
public void MenuCompletions_Navigation4()
{
Skip.If(ScreenReaderModeEnabled, "Menu completions are not supported in screen reader mode.");
// Test 'UpArrow' and 'DownArrow' with the following menu:
// Get-Less0 Get-Less3 Get-Less6 Get-Less9 Get-Less12
// Get-Less1 Get-Less4 Get-Less7 Get-Less10
// Get-Less2 Get-Less5 Get-Less8 Get-Less11
TestSetup(KeyMode.Cmd, new KeyHandler("Ctrl+Spacebar", PSConsoleReadLine.MenuComplete));
_console.Clear();
Test("Get-Less0", Keys(
"Get-Less", _.Ctrl_Spacebar,
CheckThat(() => AssertScreenIs(4,
TokenClassification.Command, "Get-Less",
TokenClassification.Selection, "0", NextLine,
TokenClassification.Selection, "Get-Less0 ",
TokenClassification.None,
"Get-Less3 Get-Less6 Get-Less9 Get-Less12", NextLine,
"Get-Less1 Get-Less4 Get-Less7 Get-Less10", NextLine,
"Get-Less2 Get-Less5 Get-Less8 Get-Less11")),
_.DownArrow,
CheckThat(() => AssertScreenIs(4,
TokenClassification.Command, "Get-Less",
TokenClassification.Selection, "1", NextLine,
TokenClassification.None,
"Get-Less0 Get-Less3 Get-Less6 Get-Less9 Get-Less12", NextLine,
TokenClassification.Selection, "Get-Less1 ",
TokenClassification.None,
"Get-Less4 Get-Less7 Get-Less10", NextLine,
"Get-Less2 Get-Less5 Get-Less8 Get-Less11")),
_.DownArrow,
CheckThat(() => AssertScreenIs(4,
TokenClassification.Command, "Get-Less",
TokenClassification.Selection, "2", NextLine,
TokenClassification.None,
"Get-Less0 Get-Less3 Get-Less6 Get-Less9 Get-Less12", NextLine,
"Get-Less1 Get-Less4 Get-Less7 Get-Less10", NextLine,
TokenClassification.Selection, "Get-Less2 ",
TokenClassification.None,
"Get-Less5 Get-Less8 Get-Less11")),
_.DownArrow,
CheckThat(() => AssertScreenIs(4,
TokenClassification.Command, "Get-Less",
TokenClassification.Selection, "3", NextLine,
TokenClassification.None, "Get-Less0 ",
TokenClassification.Selection, "Get-Less3 ",
TokenClassification.None,
"Get-Less6 Get-Less9 Get-Less12", NextLine,
"Get-Less1 Get-Less4 Get-Less7 Get-Less10", NextLine,
"Get-Less2 Get-Less5 Get-Less8 Get-Less11")),
_.UpArrow,
CheckThat(() => AssertScreenIs(4,
TokenClassification.Command, "Get-Less",
TokenClassification.Selection, "2", NextLine,
TokenClassification.None,
"Get-Less0 Get-Less3 Get-Less6 Get-Less9 Get-Less12", NextLine,
"Get-Less1 Get-Less4 Get-Less7 Get-Less10", NextLine,
TokenClassification.Selection, "Get-Less2 ",
TokenClassification.None,
"Get-Less5 Get-Less8 Get-Less11")),
_.UpArrow, _.UpArrow,
CheckThat(() => AssertScreenIs(4,
TokenClassification.Command, "Get-Less",
TokenClassification.Selection, "0", NextLine,
TokenClassification.Selection, "Get-Less0 ",
TokenClassification.None,
"Get-Less3 Get-Less6 Get-Less9 Get-Less12", NextLine,
"Get-Less1 Get-Less4 Get-Less7 Get-Less10", NextLine,
"Get-Less2 Get-Less5 Get-Less8 Get-Less11")),
_.UpArrow,
CheckThat(() => AssertScreenIs(4,
TokenClassification.Command, "Get-Less",
TokenClassification.Selection, "12", NextLine,
TokenClassification.None, "Get-Less0 Get-Less3 Get-Less6 Get-Less9 ",
TokenClassification.Selection, "Get-Less12 ", NextLine,
TokenClassification.None,
"Get-Less1 Get-Less4 Get-Less7 Get-Less10", NextLine,
"Get-Less2 Get-Less5 Get-Less8 Get-Less11")),
_.UpArrow,
CheckThat(() => AssertScreenIs(4,
TokenClassification.Command, "Get-Less",
TokenClassification.Selection, "11", NextLine,
TokenClassification.None,
"Get-Less0 Get-Less3 Get-Less6 Get-Less9 Get-Less12", NextLine,
"Get-Less1 Get-Less4 Get-Less7 Get-Less10", NextLine,
"Get-Less2 Get-Less5 Get-Less8 ",
TokenClassification.Selection, "Get-Less11 ")),
_.DownArrow, _.DownArrow,
CheckThat(() => AssertScreenIs(4,
TokenClassification.Command, "Get-Less",
TokenClassification.Selection, "0", NextLine,
TokenClassification.Selection, "Get-Less0 ",
TokenClassification.None,
"Get-Less3 Get-Less6 Get-Less9 Get-Less12", NextLine,
"Get-Less1 Get-Less4 Get-Less7 Get-Less10", NextLine,
"Get-Less2 Get-Less5 Get-Less8 Get-Less11")),
_.Enter,
_.Enter
));
}
[SkippableFact]
public void MenuCompletions_Navigation5()
{
// Test 'UpArrow', 'DownArrow', 'LeftArrow', and 'RightArrow' with the following menu:
// Get-MockDynamicParameters Get-Module
TestSetup(KeyMode.Cmd, new KeyHandler("Ctrl+Spacebar", PSConsoleReadLine.MenuComplete));
_console.Clear();
Test("Get-MockDynamicParameters", Keys(
"Get-Mo", _.Ctrl_Spacebar,
CheckThat(() => AssertScreenIs(2,
TokenClassification.Command, "Get-Mo",
TokenClassification.Selection, "ckDynamicParameters", NextLine,
TokenClassification.Selection, "Get-MockDynamicParameters ",
TokenClassification.None, "Get-Module")),
_.RightArrow,
CheckThat(() => AssertScreenIs(4,
TokenClassification.Command, "Get-Mo",
TokenClassification.Selection, "dule", NextLine,
TokenClassification.None, "Get-MockDynamicParameters ",
TokenClassification.Selection, "Get-Module ")),
_.RightArrow,
CheckThat(() => AssertScreenIs(2,
TokenClassification.Command, "Get-Mo",
TokenClassification.Selection, "ckDynamicParameters", NextLine,
TokenClassification.Selection, "Get-MockDynamicParameters ",
TokenClassification.None, "Get-Module")),
_.LeftArrow,
CheckThat(() => AssertScreenIs(4,
TokenClassification.Command, "Get-Mo",
TokenClassification.Selection, "dule", NextLine,
TokenClassification.None, "Get-MockDynamicParameters ",
TokenClassification.Selection, "Get-Module ")),
_.LeftArrow,
CheckThat(() => AssertScreenIs(2,
TokenClassification.Command, "Get-Mo",
TokenClassification.Selection, "ckDynamicParameters", NextLine,
TokenClassification.Selection, "Get-MockDynamicParameters ",
TokenClassification.None, "Get-Module")),
_.UpArrow,
CheckThat(() => AssertScreenIs(4,
TokenClassification.Command, "Get-Mo",
TokenClassification.Selection, "dule", NextLine,
TokenClassification.None, "Get-MockDynamicParameters ",
TokenClassification.Selection, "Get-Module ")),
_.UpArrow,
CheckThat(() => AssertScreenIs(2,
TokenClassification.Command, "Get-Mo",
TokenClassification.Selection, "ckDynamicParameters", NextLine,
TokenClassification.Selection, "Get-MockDynamicParameters ",
TokenClassification.None, "Get-Module")),
_.DownArrow,
CheckThat(() => AssertScreenIs(4,
TokenClassification.Command, "Get-Mo",
TokenClassification.Selection, "dule", NextLine,
TokenClassification.None, "Get-MockDynamicParameters ",
TokenClassification.Selection, "Get-Module ")),
_.DownArrow,
CheckThat(() => AssertScreenIs(2,
TokenClassification.Command, "Get-Mo",
TokenClassification.Selection, "ckDynamicParameters", NextLine,
TokenClassification.Selection, "Get-MockDynamicParameters ",
TokenClassification.None, "Get-Module")),
_.Enter,
_.Enter
));
}
[SkippableFact]
public void MenuCompletions_Navigation6()
{
Skip.If(ScreenReaderModeEnabled, "Menu completions are not supported in screen reader mode.");
// Test 'UpArrow', 'DownArrow', 'LeftArrow', and 'RightArrow' with the following menu:
// Get-NewDynamicParameters Get-NewStyle
// Get-NewIdea
TestSetup(KeyMode.Cmd, new KeyHandler("Ctrl+Spacebar", PSConsoleReadLine.MenuComplete));
_console.Clear();
Test("Get-NewDynamicParameters", Keys(
"Get-New", _.Ctrl_Spacebar,
CheckThat(() => AssertScreenIs(3,
TokenClassification.Command, "Get-New",
TokenClassification.Selection, "DynamicParameters", NextLine,
TokenClassification.Selection, "Get-NewDynamicParameters ",
TokenClassification.None, "Get-NewStyle", NextLine,
TokenClassification.None, "Get-NewIdea")),
_.RightArrow,
CheckThat(() => AssertScreenIs(3,
TokenClassification.Command, "Get-New",
TokenClassification.Selection, "Style", NextLine,
TokenClassification.None, "Get-NewDynamicParameters ",
TokenClassification.Selection, "Get-NewStyle ", NextLine,
TokenClassification.None, "Get-NewIdea")),
_.RightArrow,
CheckThat(() => AssertScreenIs(3,
TokenClassification.Command, "Get-New",
TokenClassification.Selection, "Idea", NextLine,
TokenClassification.None, "Get-NewDynamicParameters Get-NewStyle", NextLine,
TokenClassification.Selection, "Get-NewIdea ")),
_.RightArrow,
CheckThat(() => AssertScreenIs(3,
TokenClassification.Command, "Get-New",
TokenClassification.Selection, "DynamicParameters", NextLine,
TokenClassification.Selection, "Get-NewDynamicParameters ",
TokenClassification.None, "Get-NewStyle", NextLine,
TokenClassification.None, "Get-NewIdea")),
_.LeftArrow,
CheckThat(() => AssertScreenIs(3,
TokenClassification.Command, "Get-New",
TokenClassification.Selection, "Idea", NextLine,
TokenClassification.None, "Get-NewDynamicParameters Get-NewStyle", NextLine,
TokenClassification.Selection, "Get-NewIdea ")),
_.LeftArrow,
CheckThat(() => AssertScreenIs(3,
TokenClassification.Command, "Get-New",
TokenClassification.Selection, "Style", NextLine,
TokenClassification.None, "Get-NewDynamicParameters ",
TokenClassification.Selection, "Get-NewStyle ", NextLine,
TokenClassification.None, "Get-NewIdea")),
_.LeftArrow,
CheckThat(() => AssertScreenIs(3,
TokenClassification.Command, "Get-New",
TokenClassification.Selection, "DynamicParameters", NextLine,
TokenClassification.Selection, "Get-NewDynamicParameters ",
TokenClassification.None, "Get-NewStyle", NextLine,
TokenClassification.None, "Get-NewIdea")),
_.DownArrow,
CheckThat(() => AssertScreenIs(3,
TokenClassification.Command, "Get-New",
TokenClassification.Selection, "Idea", NextLine,
TokenClassification.None, "Get-NewDynamicParameters Get-NewStyle", NextLine,
TokenClassification.Selection, "Get-NewIdea ")),
_.DownArrow,
CheckThat(() => AssertScreenIs(3,
TokenClassification.Command, "Get-New",
TokenClassification.Selection, "Style", NextLine,
TokenClassification.None, "Get-NewDynamicParameters ",
TokenClassification.Selection, "Get-NewStyle ", NextLine,
TokenClassification.None, "Get-NewIdea")),
_.DownArrow,
CheckThat(() => AssertScreenIs(3,
TokenClassification.Command, "Get-New",
TokenClassification.Selection, "DynamicParameters", NextLine,
TokenClassification.Selection, "Get-NewDynamicParameters ",
TokenClassification.None, "Get-NewStyle", NextLine,
TokenClassification.None, "Get-NewIdea")),
_.UpArrow,
CheckThat(() => AssertScreenIs(3,
TokenClassification.Command, "Get-New",
TokenClassification.Selection, "Style", NextLine,
TokenClassification.None, "Get-NewDynamicParameters ",
TokenClassification.Selection, "Get-NewStyle ", NextLine,
TokenClassification.None, "Get-NewIdea")),
_.UpArrow,
CheckThat(() => AssertScreenIs(3,
TokenClassification.Command, "Get-New",
TokenClassification.Selection, "Idea", NextLine,
TokenClassification.None, "Get-NewDynamicParameters Get-NewStyle", NextLine,
TokenClassification.Selection, "Get-NewIdea ")),
_.UpArrow,
CheckThat(() => AssertScreenIs(3,
TokenClassification.Command, "Get-New",
TokenClassification.Selection, "DynamicParameters", NextLine,
TokenClassification.Selection, "Get-NewDynamicParameters ",
TokenClassification.None, "Get-NewStyle", NextLine,
TokenClassification.None, "Get-NewIdea")),
_.Enter,
_.Enter
));
}
[SkippableFact]
public void MenuCompletions_Navigation7()
{
Skip.If(ScreenReaderModeEnabled, "Menu completions are not supported in screen reader mode.");
// Trigger the menu completion from the last line in the screen buffer, which will cause the screen
// to scroll up. Then test 'DownArrow' and 'UpArrow' with the following menu to verify if scrolling
// was handled correctly:
// Get-Many0 Get-Many3 Get-Many6 Get-Many9 Get-Many12
// Get-Many1 Get-Many4 Get-Many7 Get-Many10 Get-Many13
// Get-Many2 Get-Many5 Get-Many8 Get-Many11 Get-Many14
var basicScrollingConsole = new BasicScrollingConsole(keyboardLayout: _, width: 60, height: 10);
TestSetup(basicScrollingConsole, KeyMode.Cmd, new KeyHandler("Ctrl+Spacebar", PSConsoleReadLine.MenuComplete));
// Write 12 new-lines, so that the next input will be at the last line of the screen buffer.
basicScrollingConsole.Write(new string('\n', 12));
AssertCursorLeftTopIs(0, 9);
Test("Get-Many0", Keys(
"Get-Many",
CheckThat(() => AssertCursorLeftTopIs(8, 9)),
_.Ctrl_Spacebar,
// Menu completion will trigger scrolling.
CheckThat(() => AssertCursorLeftTopIs(8, 6)),
CheckThat(() => AssertScreenIs(top: 12, lines: 4,
TokenClassification.Command, "Get-Many",
TokenClassification.Selection, "0", NextLine,
TokenClassification.Selection, "Get-Many0 ",
TokenClassification.None,
"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")),
_.DownArrow,
CheckThat(() => AssertCursorLeftTopIs(8, 6)),
CheckThat(() => AssertScreenIs(top: 12, lines: 4,
TokenClassification.Command, "Get-Many",
TokenClassification.Selection, "1", NextLine,
TokenClassification.None,
"Get-Many0 Get-Many3 Get-Many6 Get-Many9 Get-Many12", NextLine,
TokenClassification.Selection, "Get-Many1 ",
TokenClassification.None,
"Get-Many4 Get-Many7 Get-Many10 Get-Many13", NextLine,
"Get-Many2 Get-Many5 Get-Many8 Get-Many11 Get-Many14")),
_.DownArrow,
CheckThat(() => AssertCursorLeftTopIs(8, 6)),
CheckThat(() => AssertScreenIs(top: 12, lines: 4,
TokenClassification.Command, "Get-Many",
TokenClassification.Selection, "2", 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,
TokenClassification.Selection, "Get-Many2 ",
TokenClassification.None,
"Get-Many5 Get-Many8 Get-Many11 Get-Many14")),
_.DownArrow,
CheckThat(() => AssertCursorLeftTopIs(8, 6)),
CheckThat(() => AssertScreenIs(top: 12, lines: 4,
TokenClassification.Command, "Get-Many",
TokenClassification.Selection, "3", NextLine,
TokenClassification.None, "Get-Many0 ",
TokenClassification.Selection, "Get-Many3 ",
TokenClassification.None,
"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")),
_.DownArrow,
CheckThat(() => AssertCursorLeftTopIs(8, 6)),
CheckThat(() => AssertScreenIs(top: 12, lines: 4,
TokenClassification.Command, "Get-Many",
TokenClassification.Selection, "4", NextLine,
TokenClassification.None,
"Get-Many0 Get-Many3 Get-Many6 Get-Many9 Get-Many12", NextLine,
"Get-Many1 ",
TokenClassification.Selection, "Get-Many4 ",
TokenClassification.None,
"Get-Many7 Get-Many10 Get-Many13", NextLine,
"Get-Many2 Get-Many5 Get-Many8 Get-Many11 Get-Many14")),
_.DownArrow,
CheckThat(() => AssertCursorLeftTopIs(8, 6)),
CheckThat(() => AssertScreenIs(top: 12, lines: 4,
TokenClassification.Command, "Get-Many",
TokenClassification.Selection, "5", 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 ",
TokenClassification.Selection, "Get-Many5 ",
TokenClassification.None,
"Get-Many8 Get-Many11 Get-Many14")),
_.UpArrow,
CheckThat(() => AssertCursorLeftTopIs(8, 6)),
CheckThat(() => AssertScreenIs(top: 12, lines: 4,
TokenClassification.Command, "Get-Many",
TokenClassification.Selection, "4", NextLine,
TokenClassification.None,
"Get-Many0 Get-Many3 Get-Many6 Get-Many9 Get-Many12", NextLine,
"Get-Many1 ",
TokenClassification.Selection, "Get-Many4 ",
TokenClassification.None,
"Get-Many7 Get-Many10 Get-Many13", NextLine,
"Get-Many2 Get-Many5 Get-Many8 Get-Many11 Get-Many14")),
_.UpArrow,
CheckThat(() => AssertCursorLeftTopIs(8, 6)),
CheckThat(() => AssertScreenIs(top: 12, lines: 4,
TokenClassification.Command, "Get-Many",
TokenClassification.Selection, "3", NextLine,
TokenClassification.None, "Get-Many0 ",
TokenClassification.Selection, "Get-Many3 ",
TokenClassification.None,
"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")),
_.UpArrow,
CheckThat(() => AssertCursorLeftTopIs(8, 6)),
CheckThat(() => AssertScreenIs(top: 12, lines: 4,
TokenClassification.Command, "Get-Many",
TokenClassification.Selection, "2", 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,
TokenClassification.Selection, "Get-Many2 ",
TokenClassification.None,
"Get-Many5 Get-Many8 Get-Many11 Get-Many14")),
_.UpArrow, _.UpArrow,
CheckThat(() => AssertCursorLeftTopIs(8, 6)),
CheckThat(() => AssertScreenIs(top: 12, lines: 4,
TokenClassification.Command, "Get-Many",
TokenClassification.Selection, "0", NextLine,
TokenClassification.Selection, "Get-Many0 ",
TokenClassification.None,
"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")),
_.LeftArrow,
CheckThat(() => AssertCursorLeftTopIs(8, 6)),
CheckThat(() => AssertScreenIs(top: 12, lines: 4,
TokenClassification.Command, "Get-Many",
TokenClassification.Selection, "14", 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 ",
TokenClassification.Selection, "Get-Many14 ", NextLine)),
_.RightArrow,
CheckThat(() => AssertCursorLeftTopIs(8, 6)),
CheckThat(() => AssertScreenIs(top: 12, lines: 4,
TokenClassification.Command, "Get-Many",
TokenClassification.Selection, "0", NextLine,
TokenClassification.Selection, "Get-Many0 ",
TokenClassification.None,
"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")),
_.Enter,
_.Enter),
resetCursor: false);
}
[SkippableFact]
public void MenuCompletions_ClearProperly()
{
TestSetup(KeyMode.Cmd, new KeyHandler("Ctrl+Spacebar", PSConsoleReadLine.MenuComplete));
_console.Clear();
int width = _console.BufferWidth;
string placeholderCommand = new string('A', width - 12); // 12 = "Get-Module".Length + 2
Test($"{placeholderCommand};Get-Module", Keys(
placeholderCommand, ';',
"Get-Mo", _.Ctrl_Spacebar,
// At this point, the editing line buffer takes 2 physical lines.
CheckThat(() => AssertScreenIs(4,
TokenClassification.Command, placeholderCommand,
TokenClassification.None, ';',
TokenClassification.Command, "Get-Mo",
TokenClassification.Selection, "ckDynamicParameters",
NextLine,
TokenClassification.Selection, "Get-MockDynamicParameters ",
TokenClassification.None, "Get-Module ",
NextLine,
NextLine)),
_.RightArrow,
// Navigating to the next item will cause the editing line to fit in
// one physical line, so the new menu is moved up and lines from the
// previous menu need to be properly cleared.
CheckThat(() => AssertScreenIs(3,
TokenClassification.Command, placeholderCommand,
TokenClassification.None, ';',
TokenClassification.Command, "Get-Mo",
TokenClassification.Selection, "dule",
NextLine,
TokenClassification.None, "Get-MockDynamicParameters ",
TokenClassification.Selection, "Get-Module ",
NextLine,
NextLine)),
_.LeftArrow,
CheckThat(() => AssertScreenIs(4,
TokenClassification.Command, placeholderCommand,
TokenClassification.None, ';',
TokenClassification.Command, "Get-Mo",
TokenClassification.Selection, "ckDynamicParameters",
NextLine,
TokenClassification.Selection, "Get-MockDynamicParameters ",
TokenClassification.None, "Get-Module ",
NextLine,
NextLine)),
_.DownArrow,
CheckThat(() => AssertScreenIs(3,
TokenClassification.Command, placeholderCommand,
TokenClassification.None, ';',
TokenClassification.Command, "Get-Mo",
TokenClassification.Selection, "dule",
NextLine,
TokenClassification.None, "Get-MockDynamicParameters ",
TokenClassification.Selection, "Get-Module ",
NextLine,
NextLine)),
_.Enter,
_.Enter
));
}
[SkippableFact]
public void MenuCompletions_WorkWithListView()
{
Skip.If(ScreenReaderModeEnabled, "List view is not supported in screen reader mode.");
TestSetup(KeyMode.Cmd, new KeyHandler("Ctrl+Spacebar", PSConsoleReadLine.MenuComplete));
int listWidth = CheckWindowSize();
var dimmedColors = Tuple.Create(ConsoleColor.White, _console.BackgroundColor);
var emphasisColors = Tuple.Create(PSConsoleReadLineOptions.DefaultEmphasisColor, _console.BackgroundColor);
using var disp = SetPrediction(PredictionSource.History, PredictionViewStyle.ListView);
_console.Clear();
SetHistory("Get-Mocha -AddMilk -AddSugar -ExtraCup", "Get-MoreBook -Kind Fiction -FlatCover");
Test("Get-Module", Keys(
"Get-Mo",
CheckThat(() => AssertScreenIs(4,
TokenClassification.Command, "Get-Mo",
NextLine,
TokenClassification.ListPrediction, "<-/2>",
TokenClassification.None, new string(' ', listWidth - 17), // 17 is the length of '<-/2>' plus '<History(2)>'.
dimmedColors, "<History(2)>",
NextLine,
TokenClassification.ListPrediction, '>',
TokenClassification.None, ' ',
emphasisColors, "Get-Mo",
TokenClassification.None, "reBook -Kind Fiction -FlatCover",
TokenClassification.None, new string(' ', listWidth - 48), // 48 is the length of '> Get-MoreBook -Kind Fiction -FlatCover' plus '[History]'.
TokenClassification.None, '[',
TokenClassification.ListPrediction, "History",
TokenClassification.None, ']',
NextLine,
TokenClassification.ListPrediction, '>',
TokenClassification.None, ' ',
emphasisColors, "Get-Mo",
TokenClassification.None, "cha -AddMilk -AddSugar -ExtraCup",
TokenClassification.None, new string(' ', listWidth - 49), // 49 is the length of '> Get-Mocha -AddMilk -AddSugar -ExtraCup' plus '[History]'.
TokenClassification.None, '[',
TokenClassification.ListPrediction, "History",
TokenClassification.None, ']')),
_.Ctrl_Spacebar,
CheckThat(() => AssertScreenIs(4,
TokenClassification.Command, "Get-Mo",
TokenClassification.Selection, "ckDynamicParameters",
NextLine,
TokenClassification.Selection, "Get-MockDynamicParameters ",
TokenClassification.None, "Get-Module",
NextLine,
NextLine,
NextLine)),
_.RightArrow,
CheckThat(() => AssertScreenIs(4,
TokenClassification.Command, "Get-Mo",
TokenClassification.Selection, "dule",
NextLine,
TokenClassification.None, "Get-MockDynamicParameters ",
TokenClassification.Selection, "Get-Module ",
NextLine,
NextLine,
NextLine)),
_.Enter,
_.Enter
));
}
[SkippableFact]
public void MenuCompletions_HandleScrolling1()
{
Skip.If(ScreenReaderModeEnabled, "Menu completions are not supported in screen reader mode.");
// This test case covers the fix to https://github.com/PowerShell/PSReadLine/issues/2928.
var basicScrollingConsole = new BasicScrollingConsole(keyboardLayout: _, width: 133, height: 10);
TestSetup(basicScrollingConsole, KeyMode.Cmd, new KeyHandler("Ctrl+Spacebar", PSConsoleReadLine.MenuComplete));
// Write 12 new-lines, so that the next input will be at the last line of the screen buffer.
basicScrollingConsole.Write(new string('\n', 12));
AssertCursorLeftTopIs(0, 9);
// Input length: 131; BufferWidth: 133. MenuComplete on '[reg' will first get '[regex', which makes the line
// fit exactly the whole buffer width, and thus will cause screen scrolling when the current line is at the
// last line of the screen buffer.
string input = @"$instMods = 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' -replace [reg] $env:HOMEPATH ,""`$env:HOMEPATH""";
Test(input, Keys(
input,
CheckThat(() => AssertCursorLeftTopIs(131, 9)),
_.Ctrl_LeftArrow, _.Ctrl_LeftArrow, _.Ctrl_LeftArrow, _.Ctrl_LeftArrow,
_.LeftArrow, _.LeftArrow,
CheckThat(() => AssertCursorLeftTopIs(98, 9)),
_.Ctrl_Spacebar,
CheckThat(() => AssertCursorLeftTopIs(98, 6)),
CheckThat(() => AssertScreenIs(top: 12, lines: 4,
TokenClassification.Variable, "$instMods",
TokenClassification.None, ' ',
TokenClassification.Operator, '=',
TokenClassification.None, ' ',
TokenClassification.String, "'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'",
TokenClassification.None, ' ',
TokenClassification.Operator, "-replace",
TokenClassification.None, " [",
TokenClassification.Type, "reg",
TokenClassification.Selection, "ex",
TokenClassification.None, "] ",
TokenClassification.Variable, "$env:HOMEPATH",
TokenClassification.None, ' ',
TokenClassification.Operator, ',',
TokenClassification.String, @"""`$env:HOMEPATH""",
TokenClassification.None, _emptyLine,
TokenClassification.Selection, "Regex ",
TokenClassification.None, "RegionInfo RegisterPSSessionConfigurationCommand", NextLine,
TokenClassification.None, "RegexCompilationInfo RegisterArgumentCompleterCommand RegistryProviderSetItemDynamicParameter")),
_.RightArrow,
CheckThat(() => AssertCursorLeftTopIs(119, 6)),
CheckThat(() => AssertScreenIs(top: 12, lines: 4,
TokenClassification.Variable, "$instMods",
TokenClassification.None, ' ',
TokenClassification.Operator, '=',
TokenClassification.None, ' ',
TokenClassification.String, "'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'",
TokenClassification.None, ' ',
TokenClassification.Operator, "-replace",
TokenClassification.None, " [",
TokenClassification.Type, "System.Globalization.Reg",
TokenClassification.Selection, "ionInfo",
TokenClassification.None, "] ",
TokenClassification.Variable, "$env:HOMEPATH",
TokenClassification.None, ' ',
TokenClassification.Operator, ',',
TokenClassification.String, @"""`$env:HOMEPATH""",
NextLine,
TokenClassification.None, "Regex ",
TokenClassification.Selection, "RegionInfo ",
TokenClassification.None, "RegisterPSSessionConfigurationCommand", NextLine,
TokenClassification.None, "RegexCompilationInfo RegisterArgumentCompleterCommand RegistryProviderSetItemDynamicParameter")),
_.Escape,
CheckThat(() => AssertCursorLeftTopIs(98, 6)),
CheckThat(() => AssertScreenIs(top: 12, lines: 4,
TokenClassification.Variable, "$instMods",
TokenClassification.None, ' ',
TokenClassification.Operator, '=',
TokenClassification.None, ' ',
TokenClassification.String, "'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'",
TokenClassification.None, ' ',
TokenClassification.Operator, "-replace",
TokenClassification.None, " [",
TokenClassification.Type, "reg",
TokenClassification.None, "] ",
TokenClassification.Variable, "$env:HOMEPATH",
TokenClassification.None, ' ',
TokenClassification.Operator, ',',
TokenClassification.String, @"""`$env:HOMEPATH""",
NextLine,
NextLine,
NextLine,
NextLine)),
_.Enter),
resetCursor: false);
}
[SkippableFact]
public void MenuCompletions_HandleScrolling2()
{
Skip.If(ScreenReaderModeEnabled, "Menu completions are not supported in screen reader mode.");
// This test case covers the fix to https://github.com/PowerShell/PSReadLine/issues/2948.
var basicScrollingConsole = new BasicScrollingConsole(keyboardLayout: _, width: 133, height: 10);
TestSetup(basicScrollingConsole, KeyMode.Cmd, new KeyHandler("Ctrl+Spacebar", PSConsoleReadLine.MenuComplete));
// Write 12 new-lines, so that the next input will be at the last line of the screen buffer.
basicScrollingConsole.Write(new string('\n', 12));
AssertCursorLeftTopIs(0, 9);
// Input length: 69; BufferWidth: 133.
// MenuComplete on '[reg' contains one entry that will make the line fit exactly the whole buffer width,
// and thus will cause screen scrolling. But that entry is not the first one in the menu.
string input = @"'AAAAAAAAAAAAAAAAAAAAA' -replace [reg] $env:HOMEPATH ,'$env:HOMEPATH'";
Test(input, Keys(
input,
CheckThat(() => AssertCursorLeftTopIs(69, 9)),
_.Ctrl_LeftArrow, _.Ctrl_LeftArrow, _.Ctrl_LeftArrow, _.Ctrl_LeftArrow,
_.LeftArrow, _.LeftArrow,
CheckThat(() => AssertCursorLeftTopIs(37, 9)),
_.Ctrl_Spacebar,
CheckThat(() => AssertCursorLeftTopIs(37, 7)),
CheckThat(() => AssertScreenIs(top: 12, lines: 3,
TokenClassification.String, "'AAAAAAAAAAAAAAAAAAAAA'",
TokenClassification.None, ' ',
TokenClassification.Operator, "-replace",
TokenClassification.None, " [",
TokenClassification.Type, "reg",
TokenClassification.Selection, "ex",
TokenClassification.None, "] ",
TokenClassification.Variable, "$env:HOMEPATH",
TokenClassification.None, ' ',
TokenClassification.Operator, ',',
TokenClassification.String, "'$env:HOMEPATH'",
NextLine,
TokenClassification.Selection, "Regex ",
TokenClassification.None, "RegionInfo RegisterPSSessionConfigurationCommand", NextLine,
TokenClassification.None, "RegexCompilationInfo RegisterArgumentCompleterCommand RegistryProviderSetItemDynamicParameter")),
_.RightArrow,
CheckThat(() => AssertCursorLeftTopIs(58, 7)),
CheckThat(() => AssertScreenIs(top: 12, lines: 3,
TokenClassification.String, "'AAAAAAAAAAAAAAAAAAAAA'",
TokenClassification.None, ' ',
TokenClassification.Operator, "-replace",
TokenClassification.None, " [",
TokenClassification.Type, "System.Globalization.Reg",
TokenClassification.Selection, "ionInfo",
TokenClassification.None, "] ",
TokenClassification.Variable, "$env:HOMEPATH",
TokenClassification.None, ' ',
TokenClassification.Operator, ',',
TokenClassification.String, "'$env:HOMEPATH'",
NextLine,
TokenClassification.None, "Regex ",
TokenClassification.Selection, "RegionInfo ",
TokenClassification.None, "RegisterPSSessionConfigurationCommand", NextLine,
TokenClassification.None, "RegexCompilationInfo RegisterArgumentCompleterCommand RegistryProviderSetItemDynamicParameter")),
_.RightArrow,
CheckThat(() => AssertCursorLeftTopIs(67, 6)),
CheckThat(() => AssertScreenIs(top: 12, lines: 4,
TokenClassification.String, "'AAAAAAAAAAAAAAAAAAAAA'",
TokenClassification.None, ' ',
TokenClassification.Operator, "-replace",
TokenClassification.None, " [",
TokenClassification.Type, "Microsoft.PowerShell.Commands.Reg",
TokenClassification.Selection, "isterPSSessionConfigurationCommand",
TokenClassification.None, "] ",
TokenClassification.Variable, "$env:HOMEPATH",
TokenClassification.None, ' ',
TokenClassification.Operator, ',',
TokenClassification.String, "'$env:HOMEPATH'",
TokenClassification.None, _emptyLine,
TokenClassification.None, "Regex RegionInfo ",
TokenClassification.Selection, "RegisterPSSessionConfigurationCommand ", NextLine,
TokenClassification.None, "RegexCompilationInfo RegisterArgumentCompleterCommand RegistryProviderSetItemDynamicParameter")),
_.RightArrow,
CheckThat(() => AssertCursorLeftTopIs(49, 6)),
CheckThat(() => AssertScreenIs(top: 12, lines: 4,
TokenClassification.String, "'AAAAAAAAAAAAAAAAAAAAA'",
TokenClassification.None, ' ',
TokenClassification.Operator, "-replace",
TokenClassification.None, " [",
TokenClassification.Type, "System.Text.Reg",
TokenClassification.Selection, "ularExpressions.RegexCompilationInfo",
TokenClassification.None, "] ",
TokenClassification.Variable, "$env:HOMEPATH",
TokenClassification.None, ' ',
TokenClassification.Operator, ',',
TokenClassification.String, "'$env:HOMEPATH'",
NextLine,
TokenClassification.None, "Regex RegionInfo RegisterPSSessionConfigurationCommand",
NextLine,
TokenClassification.Selection, "RegexCompilationInfo ",
TokenClassification.None, "RegisterArgumentCompleterCommand RegistryProviderSetItemDynamicParameter",
NextLine,
NextLine)),
_.RightArrow,
CheckThat(() => AssertCursorLeftTopIs(66, 6)),
CheckThat(() => AssertScreenIs(top: 12, lines: 4,
TokenClassification.String, "'AAAAAAAAAAAAAAAAAAAAA'",
TokenClassification.None, ' ',
TokenClassification.Operator, "-replace",
TokenClassification.None, " [",
TokenClassification.Type, "System.Management.Automation.Reg",
TokenClassification.Selection, "isterArgumentCompleterCommand",
TokenClassification.None, "] ",
TokenClassification.Variable, "$env:HOMEPATH",
TokenClassification.None, ' ',
TokenClassification.Operator, ',',
TokenClassification.String, "'$env:HOMEPATH'",
NextLine,
TokenClassification.None, "Regex RegionInfo RegisterPSSessionConfigurationCommand",
NextLine,
TokenClassification.None, "RegexCompilationInfo ",
TokenClassification.Selection, "RegisterArgumentCompleterCommand ",
TokenClassification.None, "RegistryProviderSetItemDynamicParameter",
NextLine,
NextLine)),
_.RightArrow,
CheckThat(() => AssertCursorLeftTopIs(67, 6)),
CheckThat(() => AssertScreenIs(top: 12, lines: 4,
TokenClassification.String, "'AAAAAAAAAAAAAAAAAAAAA'",
TokenClassification.None, ' ',
TokenClassification.Operator, "-replace",
TokenClassification.None, " [",
TokenClassification.Type, "Microsoft.PowerShell.Commands.Reg",
TokenClassification.Selection, "istryProviderSetItemDynamicParameter",
TokenClassification.None, "] ",
TokenClassification.Variable, "$env:HOMEPATH",
TokenClassification.None, ' ',
TokenClassification.Operator, ',',
TokenClassification.String, "'$env:HOMEPATH'",
NextLine,
TokenClassification.None, "Regex RegionInfo RegisterPSSessionConfigurationCommand",
NextLine,
TokenClassification.None, "RegexCompilationInfo RegisterArgumentCompleterCommand ",
TokenClassification.Selection, "RegistryProviderSetItemDynamicParameter ",
NextLine)),
_.Escape,
CheckThat(() => AssertCursorLeftTopIs(37, 6)),
CheckThat(() => AssertScreenIs(top: 12, lines: 4,
TokenClassification.String, "'AAAAAAAAAAAAAAAAAAAAA'",
TokenClassification.None, ' ',
TokenClassification.Operator, "-replace",
TokenClassification.None, " [",
TokenClassification.Type, "reg",
TokenClassification.None, "] ",
TokenClassification.Variable, "$env:HOMEPATH",
TokenClassification.None, ' ',
TokenClassification.Operator, ',',
TokenClassification.String, "'$env:HOMEPATH'",
NextLine,
NextLine,
NextLine,
NextLine)),
_.Enter),
resetCursor: false);
}
[SkippableFact]
public void ShowTooltips()
{
TestSetup(KeyMode.Cmd, new KeyHandler("Ctrl+Spacebar", PSConsoleReadLine.PossibleCompletions));
PSConsoleReadLine.GetOptions().ShowToolTips = true;
_console.Clear();
// TODO:
}
[SkippableFact]
public void DirectoryCompletion()
{
TestSetup(KeyMode.Cmd);
Test("", Keys(
"Get-Directory", _.Tab,
CheckThat(() => AssertLineIs("abc" + Path.DirectorySeparatorChar)),
_.Tab,
CheckThat(() => AssertLineIs("'e f" + Path.DirectorySeparatorChar + "'")),
CheckThat(() => AssertCursorLeftIs(5)),
_.Tab,
CheckThat(() => AssertLineIs("a" + Path.DirectorySeparatorChar)),
_.Tab,
CheckThat(() => AssertLineIs("'a b" + Path.DirectorySeparatorChar + "'")),
CheckThat(() => AssertCursorLeftIs(5)),
_.Tab,
CheckThat(() => AssertLineIs("\"a b" + Path.DirectorySeparatorChar + "\"")),
CheckThat(() => AssertCursorLeftIs(5)),
_.Ctrl_c, InputAcceptedNow));
}
[SkippableFact]
public void MenuCompletions_Backspace()
{
TestSetup(KeyMode.Cmd, new KeyHandler("Ctrl+Spacebar", PSConsoleReadLine.MenuComplete));
_console.Clear();
char separator = Path.DirectorySeparatorChar;
Test("cd stro", Keys(
"cd stron", _.Ctrl_Spacebar,
CheckThat(() => AssertScreenIs(3,
TokenClassification.Command, "cd",
TokenClassification.None, $" .{separator}strong",
TokenClassification.Selection, separator,
NextLine,
TokenClassification.Selection, "strong ",
TokenClassification.None, "stronghold strongholp",
NextLine,
NextLine)),
_.h, CheckThat(() => AssertScreenIs(3,
TokenClassification.Command, "cd",
TokenClassification.None, $" .{separator}strongh",
TokenClassification.Selection, $"old{separator}",
NextLine,
TokenClassification.Selection, "stronghold ",
TokenClassification.None, "strongholp",
NextLine,
NextLine)),
// Tab will update the user completion text to include the unambiguous common prefix.
_.Tab, CheckThat(() => AssertScreenIs(3,
TokenClassification.Command, "cd",
TokenClassification.None, $" .{separator}stronghol",
TokenClassification.Selection, $"d{separator}",
NextLine,
TokenClassification.Selection, "stronghold ",
TokenClassification.None, "strongholp",
NextLine,
NextLine)),
_.Backspace, CheckThat(() => AssertScreenIs(3,
TokenClassification.Command, "cd",
TokenClassification.None, $" .{separator}strongho",
TokenClassification.Selection, $"ld{separator}",
NextLine,
TokenClassification.Selection, "stronghold ",
TokenClassification.None, "strongholp",
NextLine,
NextLine)),
_.Backspace, CheckThat(() => AssertScreenIs(3,
TokenClassification.Command, "cd",
TokenClassification.None, $" .{separator}strongh",
TokenClassification.Selection, $"old{separator}",
NextLine,
TokenClassification.Selection, "stronghold ",
TokenClassification.None, "strongholp",
NextLine,
NextLine)),
_.Backspace, CheckThat(() => AssertScreenIs(3,
TokenClassification.Command, "cd",
TokenClassification.None, $" .{separator}strong",
TokenClassification.Selection, separator,
NextLine,
TokenClassification.Selection, "strong ",
TokenClassification.None, "stronghold strongholp",
NextLine,
NextLine)),
_.h, CheckThat(() => AssertScreenIs(3,
TokenClassification.Command, "cd",
TokenClassification.None, $" .{separator}strongh",
TokenClassification.Selection, $"old{separator}",
NextLine,
TokenClassification.Selection, "stronghold ",
TokenClassification.None, "strongholp",
NextLine,
NextLine)),
_.Backspace, CheckThat(() => AssertScreenIs(3,
TokenClassification.Command, "cd",
TokenClassification.None, $" .{separator}strong",
TokenClassification.Selection, separator,
NextLine,
TokenClassification.Selection, "strong ",
TokenClassification.None, "stronghold strongholp",
NextLine,
NextLine)),
_.Backspace,
_.Backspace, CheckThat(() => AssertLineIs("cd stro")),
_.Enter
));
}
internal static CommandCompletion MockedCompleteInput(string input, int cursor, Hashtable options, PowerShell powerShell)
{
var ctor = typeof (CommandCompletion).GetConstructor(
BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance, null,
new [] {typeof (Collection<CompletionResult>), typeof (int), typeof (int), typeof (int)}, null);
var completions = new Collection<CompletionResult>();
const int currentMatchIndex = -1;
var replacementIndex = 0;
var replacementLength = 0;
switch (input)
{
case "$t":
replacementIndex = 0;
replacementLength = 2;
completions.Add(new CompletionResult("$thing"));
completions.Add(new CompletionResult("$this"));
completions.Add(new CompletionResult("$true"));
break;
case "$tr":
replacementIndex = 0;
replacementLength = 3;
completions.Add(new CompletionResult("$true"));
break;
case "psvar":
replacementIndex = 0;
replacementLength = 5;
completions.Add(new CompletionResult("$pssomething"));
break;
case "ambig":
replacementIndex = 0;
replacementLength = 5;
completions.Add(new CompletionResult("ambiguous1"));
completions.Add(new CompletionResult("ambiguous2"));
completions.Add(new CompletionResult("ambiguous3"));
break;
case "Get-Many":
replacementIndex = 0;
replacementLength = 8;
for (int i = 0; i < 15; i++)
{
completions.Add(new CompletionResult("Get-Many" + i));
}
break;
case "Get-Less":
replacementIndex = 0;
replacementLength = 8;
for (int i = 0; i < 13; i++)
{
completions.Add(new CompletionResult("Get-Less" + i));
}
break;
case "Get-New":
replacementIndex = 0;
replacementLength = 7;
completions.Add(new CompletionResult("Get-NewDynamicParameters"));
completions.Add(new CompletionResult("Get-NewIdea"));
completions.Add(new CompletionResult("Get-NewStyle"));
break;
case "Get-Tooltips":
replacementIndex = 0;
replacementLength = 12;
completions.Add(new CompletionResult("something really long", "item1", CompletionResultType.Command, "useful description goes here"));
break;
case "Get-Directory":
replacementIndex = 0;
replacementLength = 13;
completions.Add(new CompletionResult("abc", "abc", CompletionResultType.ProviderContainer, "abc"));
completions.Add(new CompletionResult("'e f'", "'e f'", CompletionResultType.ProviderContainer, "'e f'"));
completions.Add(new CompletionResult("a", "a", CompletionResultType.ProviderContainer, "a"));
completions.Add(new CompletionResult("'a b" + Path.DirectorySeparatorChar + "'", "a b" + Path.DirectorySeparatorChar + "'", CompletionResultType.ProviderContainer, "a b" + Path.DirectorySeparatorChar + "'"));
completions.Add(new CompletionResult("\"a b" + Path.DirectorySeparatorChar + "\"", "\"a b" + Path.DirectorySeparatorChar + "\"", CompletionResultType.ProviderContainer, "\"a b" + Path.DirectorySeparatorChar + "\""));
break;
case "invalid result 1":
replacementIndex = -1;
replacementLength = 1;
completions.Add(new CompletionResult("result"));
break;
case "invalid result 2":
replacementIndex = 0;
replacementLength = -1;
completions.Add(new CompletionResult("result"));
break;
case "invalid result 3":
replacementIndex = int.MaxValue;
replacementLength = 1;
completions.Add(new CompletionResult("result"));
break;
case "invalid result 4":
replacementIndex = 0;
replacementLength = int.MaxValue;
completions.Add(new CompletionResult("result"));
break;
case "ls -H":
replacementIndex = cursor;
replacementLength = 0;
completions.Add(new CompletionResult("idden"));
break;
case "none":
break;
case "cd stron":
replacementIndex = 3;
replacementLength = 5;
char separator = Path.DirectorySeparatorChar;
completions.Add(new CompletionResult($".{separator}strong", "strong", CompletionResultType.ProviderContainer, $".{separator}strong"));
completions.Add(new CompletionResult($".{separator}stronghold", "stronghold", CompletionResultType.ProviderContainer, $".{separator}stronghold"));
completions.Add(new CompletionResult($".{separator}strongholp", "strongholp", CompletionResultType.ProviderContainer, $".{separator}strongholp"));
break;
default:
if (input.EndsWith("Get-Mo", StringComparison.OrdinalIgnoreCase))
{
replacementIndex = input.IndexOf("Get-Mo", StringComparison.OrdinalIgnoreCase);
replacementLength = 6;
completions.Add(new CompletionResult("Get-MockDynamicParameters"));
completions.Add(new CompletionResult("Get-Module"));
break;
}
int index = input.IndexOf("[reg]");
if (index > 0 && index + 4 == cursor)
{
// cursor is pointing at ']'.
replacementIndex = index + 1;
replacementLength = 3;
completions.Add(
new CompletionResult(
"regex",
"Regex",
CompletionResultType.Type,
"regex"));
completions.Add(
new CompletionResult(
"System.Text.RegularExpressions.RegexCompilationInfo",
"RegexCompilationInfo",
CompletionResultType.Type,
"System.Text.RegularExpressions.RegexCompilationInfo"));
completions.Add(
new CompletionResult(
"System.Globalization.RegionInfo",
"RegionInfo",
CompletionResultType.Type,
"System.Globalization.RegionInfo"));
completions.Add(
new CompletionResult(
"System.Management.Automation.RegisterArgumentCompleterCommand",
"RegisterArgumentCompleterCommand",
CompletionResultType.Type,
"System.Management.Automation.RegisterArgumentCompleterCommand"));
completions.Add(
new CompletionResult(
"Microsoft.PowerShell.Commands.RegisterPSSessionConfigurationCommand",
"RegisterPSSessionConfigurationCommand",
CompletionResultType.Type,
"Microsoft.PowerShell.Commands.RegisterPSSessionConfigurationCommand"));
completions.Add(
new CompletionResult(
"Microsoft.PowerShell.Commands.RegistryProviderSetItemDynamicParameter",
"RegistryProviderSetItemDynamicParameter",
CompletionResultType.Type,
"Microsoft.PowerShell.Commands.RegistryProviderSetItemDynamicParameter"));
break;
}
break;
}
//new CommandCompletion(completions, currentMatchIndex, replacementIndex, replacementLength);
return (CommandCompletion)ctor.Invoke(
new object[] {completions, currentMatchIndex, replacementIndex, replacementLength});
}
}
}