mirror of
https://github.com/PowerShell/PSReadLine
synced 2026-06-08 12:12:13 +00:00
342 lines
17 KiB
C#
342 lines
17 KiB
C#
using Microsoft.PowerShell;
|
|
using Xunit;
|
|
|
|
namespace Test
|
|
{
|
|
public partial class ReadLine
|
|
{
|
|
[SkippableFact]
|
|
public void EndOfLine()
|
|
{
|
|
TestSetup(KeyMode.Cmd);
|
|
|
|
Test("", Keys( _.End, CheckThat(() => AssertCursorLeftIs(0)) ));
|
|
|
|
Test(_emptyLine, Keys(
|
|
_emptyLine,
|
|
_.Home,
|
|
CheckThat(() => AssertCursorLeftIs(0)),
|
|
_.End,
|
|
CheckThat(() => AssertCursorLeftTopIs(0, 1))
|
|
));
|
|
|
|
var buffer = new string(' ', _console.BufferWidth + 5);
|
|
Test(buffer, Keys(
|
|
buffer,
|
|
_.Home,
|
|
CheckThat(() => AssertCursorLeftIs(0)),
|
|
_.End,
|
|
CheckThat(() => AssertCursorLeftTopIs(5, 1))
|
|
));
|
|
}
|
|
|
|
[SkippableFact]
|
|
public void MultilineCursorMovement_WithWrappedLines()
|
|
{
|
|
TestSetup(KeyMode.Cmd);
|
|
|
|
int continutationPromptLength = PSConsoleReadLineOptions.DefaultContinuationPrompt.Length;
|
|
string line_0 = "4444";
|
|
string line_1 = "33";
|
|
string line_2 = "666666";
|
|
string line_3 = "777";
|
|
|
|
int wrappedLength_1 = 9;
|
|
int wrappedLength_2 = 2;
|
|
string wrappedLine_1 = new string('8', _console.BufferWidth - continutationPromptLength + wrappedLength_1); // Take 2 physical lines
|
|
string wrappedLine_2 = new string('6', _console.BufferWidth - continutationPromptLength + wrappedLength_2); // Take 2 physical lines
|
|
|
|
Test("", Keys(
|
|
"", _.Shift_Enter, // physical line 0
|
|
line_0, _.Shift_Enter, // physical line 1
|
|
line_1, _.Shift_Enter, // physical line 2
|
|
line_2, _.Shift_Enter, // physical line 3
|
|
wrappedLine_1, _.Shift_Enter, // physical line 4,5
|
|
wrappedLine_2, _.Shift_Enter, // physical line 6,7
|
|
line_3, // physical line 8
|
|
|
|
// Starting at the end of the last line.
|
|
// Verify that UpArrow goes to the end of the previous logical line.
|
|
CheckThat(() => AssertCursorLeftTopIs(continutationPromptLength + line_3.Length, 8)),
|
|
_.DownArrow, CheckThat(() => AssertCursorLeftTopIs(continutationPromptLength + line_3.Length, 8)),
|
|
_.DownArrow, CheckThat(() => AssertCursorLeftTopIs(continutationPromptLength + line_3.Length, 8)),
|
|
// Press Up/Down/Up
|
|
_.UpArrow, CheckThat(() => AssertCursorLeftTopIs(wrappedLength_2, 7)),
|
|
_.DownArrow, CheckThat(() => AssertCursorLeftTopIs(continutationPromptLength + line_3.Length, 8)),
|
|
_.UpArrow, CheckThat(() => AssertCursorLeftTopIs(wrappedLength_2, 7)),
|
|
// Press Up/Down/Up
|
|
_.UpArrow, CheckThat(() => AssertCursorLeftTopIs(wrappedLength_1, 5)),
|
|
_.DownArrow, CheckThat(() => AssertCursorLeftTopIs(wrappedLength_2, 7)),
|
|
_.UpArrow, CheckThat(() => AssertCursorLeftTopIs(wrappedLength_1, 5)),
|
|
// Press Up/Down/Up
|
|
_.UpArrow, CheckThat(() => AssertCursorLeftTopIs(continutationPromptLength + line_2.Length, 3)),
|
|
_.DownArrow, CheckThat(() => AssertCursorLeftTopIs(wrappedLength_1, 5)),
|
|
_.UpArrow, CheckThat(() => AssertCursorLeftTopIs(continutationPromptLength + line_2.Length, 3)),
|
|
// Press Up/Up
|
|
_.UpArrow, CheckThat(() => AssertCursorLeftTopIs(continutationPromptLength + line_1.Length, 2)),
|
|
_.UpArrow, CheckThat(() => AssertCursorLeftTopIs(continutationPromptLength + line_0.Length, 1)),
|
|
|
|
// Move to left for 1 character, so the cursor now is not at the end of line.
|
|
// Verify that DownArrow/UpArrow goes to the previous logical line at the same column.
|
|
_.LeftArrow, CheckThat(() => AssertCursorLeftTopIs(continutationPromptLength + line_0.Length - 1, 1)),
|
|
// Press Down all the way to the end
|
|
_.DownArrow, CheckThat(() => AssertCursorLeftTopIs(continutationPromptLength + line_1.Length, 2)),
|
|
_.DownArrow, CheckThat(() => AssertCursorLeftTopIs(continutationPromptLength + line_0.Length - 1, 3)),
|
|
_.DownArrow, CheckThat(() => AssertCursorLeftTopIs(continutationPromptLength + line_0.Length - 1, 4)),
|
|
_.DownArrow, CheckThat(() => AssertCursorLeftTopIs(continutationPromptLength + line_0.Length - 1, 5)),
|
|
_.DownArrow, CheckThat(() => AssertCursorLeftTopIs(continutationPromptLength + line_0.Length - 1, 6)),
|
|
_.DownArrow, CheckThat(() => AssertCursorLeftTopIs(wrappedLength_2, 7)),
|
|
_.DownArrow, CheckThat(() => AssertCursorLeftTopIs(continutationPromptLength + line_3.Length, 8)),
|
|
_.DownArrow, CheckThat(() => AssertCursorLeftTopIs(continutationPromptLength + line_3.Length, 8)),
|
|
// Press Up all the way to the physical line 1
|
|
_.UpArrow, CheckThat(() => AssertCursorLeftTopIs(wrappedLength_2, 7)),
|
|
_.UpArrow, CheckThat(() => AssertCursorLeftTopIs(continutationPromptLength + line_0.Length - 1, 6)),
|
|
_.UpArrow, CheckThat(() => AssertCursorLeftTopIs(continutationPromptLength + line_0.Length - 1, 5)),
|
|
_.UpArrow, CheckThat(() => AssertCursorLeftTopIs(continutationPromptLength + line_0.Length - 1, 4)),
|
|
_.UpArrow, CheckThat(() => AssertCursorLeftTopIs(continutationPromptLength + line_0.Length - 1, 3)),
|
|
_.UpArrow, CheckThat(() => AssertCursorLeftTopIs(continutationPromptLength + line_1.Length, 2)),
|
|
_.UpArrow, CheckThat(() => AssertCursorLeftTopIs(continutationPromptLength + line_0.Length - 1, 1)),
|
|
|
|
// Clear the input, we were just testing movement
|
|
_.Escape
|
|
));
|
|
}
|
|
|
|
[SkippableFact]
|
|
public void MultilineCursorMovement()
|
|
{
|
|
TestSetup(KeyMode.Cmd);
|
|
|
|
var continutationPromptLength = PSConsoleReadLineOptions.DefaultContinuationPrompt.Length;
|
|
Test("", Keys(
|
|
"4444", _.Shift_Enter,
|
|
"666666", _.Shift_Enter,
|
|
"88888888", _.Shift_Enter,
|
|
"666666", _.Shift_Enter,
|
|
"4444", _.Shift_Enter,
|
|
|
|
// Starting at the end of the next to last line (because it's not blank)
|
|
// Verify that Home first goes to the start of the line, then the start of the input.
|
|
_.LeftArrow,
|
|
_.Home, CheckThat(() => AssertCursorLeftTopIs(continutationPromptLength, 4)),
|
|
_.Home, CheckThat(() => AssertCursorLeftTopIs(0, 0)),
|
|
|
|
// Now (because we're at the start), verify first End goes to end of the line
|
|
// and the second End goes to the end of the input.
|
|
_.End, CheckThat(() => AssertCursorLeftTopIs(4, 0)),
|
|
_.End, CheckThat(() => AssertCursorLeftTopIs(0 + continutationPromptLength, 5)),
|
|
|
|
_.Home, _.Home,
|
|
_.DownArrow, CheckThat(() => AssertCursorLeftTopIs(continutationPromptLength, 1)),
|
|
_.DownArrow, CheckThat(() => AssertCursorLeftTopIs(continutationPromptLength, 2)),
|
|
_.DownArrow, CheckThat(() => AssertCursorLeftTopIs(continutationPromptLength, 3)),
|
|
_.DownArrow, CheckThat(() => AssertCursorLeftTopIs(continutationPromptLength, 4)),
|
|
_.DownArrow, CheckThat(() => AssertCursorLeftTopIs(continutationPromptLength, 5)),
|
|
_.LeftArrow, _.Home,
|
|
_.UpArrow, CheckThat(() => AssertCursorLeftTopIs(continutationPromptLength, 3)),
|
|
_.UpArrow, CheckThat(() => AssertCursorLeftTopIs(continutationPromptLength, 2)),
|
|
_.UpArrow, CheckThat(() => AssertCursorLeftTopIs(continutationPromptLength, 1)),
|
|
_.UpArrow, CheckThat(() => AssertCursorLeftTopIs(continutationPromptLength, 0)), // was (4,0), but seems wrong
|
|
|
|
// Make sure that movement between lines stays at the end of a line if it starts
|
|
// at the end of a line
|
|
_.End, _.End,
|
|
_.UpArrow, CheckThat(() => AssertCursorLeftTopIs(4 + continutationPromptLength, 4)),
|
|
_.UpArrow, CheckThat(() => AssertCursorLeftTopIs(6 + continutationPromptLength, 3)),
|
|
_.UpArrow, CheckThat(() => AssertCursorLeftTopIs(8 + continutationPromptLength, 2)),
|
|
_.UpArrow, CheckThat(() => AssertCursorLeftTopIs(6 + continutationPromptLength, 1)),
|
|
_.UpArrow, CheckThat(() => AssertCursorLeftTopIs(4, 0)),
|
|
_.DownArrow, CheckThat(() => AssertCursorLeftTopIs(6 + continutationPromptLength, 1)),
|
|
_.DownArrow, CheckThat(() => AssertCursorLeftTopIs(8 + continutationPromptLength, 2)),
|
|
_.DownArrow, CheckThat(() => AssertCursorLeftTopIs(6 + continutationPromptLength, 3)),
|
|
_.DownArrow, CheckThat(() => AssertCursorLeftTopIs(4 + continutationPromptLength, 4)),
|
|
_.DownArrow, CheckThat(() => AssertCursorLeftTopIs(0 + continutationPromptLength, 5)),
|
|
|
|
_.Escape,
|
|
_.Shift_Enter,
|
|
"88888888", _.Shift_Enter,
|
|
"55555", _.Shift_Enter,
|
|
"22", _.Shift_Enter,
|
|
"55555", _.Shift_Enter,
|
|
"88888888",
|
|
_.LeftArrow, _.LeftArrow,
|
|
_.UpArrow, CheckThat(() => AssertCursorLeftTopIs(5 + continutationPromptLength, 4)),
|
|
_.UpArrow, CheckThat(() => AssertCursorLeftTopIs(2 + continutationPromptLength, 3)),
|
|
_.UpArrow, CheckThat(() => AssertCursorLeftTopIs(5 + continutationPromptLength, 2)),
|
|
_.UpArrow, CheckThat(() => AssertCursorLeftTopIs(6 + continutationPromptLength, 1)),
|
|
_.UpArrow, CheckThat(() => AssertCursorLeftTopIs(0, 0)),
|
|
_.UpArrow, CheckThat(() => AssertCursorLeftTopIs(0, 0)),
|
|
_.DownArrow, CheckThat(() => AssertCursorLeftTopIs(6 + continutationPromptLength, 1)),
|
|
_.DownArrow, CheckThat(() => AssertCursorLeftTopIs(5 + continutationPromptLength, 2)),
|
|
_.DownArrow, CheckThat(() => AssertCursorLeftTopIs(2 + continutationPromptLength, 3)),
|
|
_.DownArrow, CheckThat(() => AssertCursorLeftTopIs(5 + continutationPromptLength, 4)),
|
|
_.DownArrow, CheckThat(() => AssertCursorLeftTopIs(6 + continutationPromptLength, 5)),
|
|
|
|
// Using the input previously entered, check for correct cursor movements when first line is blank
|
|
_.Home, _.Home, CheckThat(() => AssertCursorLeftTopIs(0, 0)),
|
|
_.DownArrow, CheckThat(() => AssertCursorLeftTopIs(8 + continutationPromptLength, 1)),
|
|
_.Home, CheckThat(() => AssertCursorLeftTopIs(continutationPromptLength, 1)),
|
|
_.Home, CheckThat(() => AssertCursorLeftTopIs(0,0)),
|
|
|
|
// Clear the input, we were just testing movement
|
|
_.Escape
|
|
));
|
|
}
|
|
|
|
[SkippableFact]
|
|
public void CursorMovement()
|
|
{
|
|
TestSetup(KeyMode.Cmd);
|
|
|
|
Test("abcde", Keys(
|
|
// Left arrow at start of line.
|
|
_.LeftArrow, CheckThat(() => AssertCursorLeftIs(0)),
|
|
"ace",
|
|
_.LeftArrow, CheckThat(() => AssertCursorLeftIs(2)),
|
|
'd',
|
|
_.LeftArrow, CheckThat(() => AssertCursorLeftIs(2)),
|
|
_.LeftArrow, CheckThat(() => AssertCursorLeftIs(1)),
|
|
'b'
|
|
));
|
|
|
|
// Test with digit arguments
|
|
var input = "0123456789";
|
|
Test(input, Keys(
|
|
_.Alt_9, _.LeftArrow, CheckThat(() => AssertCursorLeftIs(0)),
|
|
_.Alt_9, _.RightArrow, CheckThat(() => AssertCursorLeftIs(0)),
|
|
input,
|
|
_.Alt_5, _.LeftArrow, CheckThat(() => AssertCursorLeftIs(5)),
|
|
_.Alt_Minus, _.Alt_2, _.LeftArrow, CheckThat(() => AssertCursorLeftIs(7)),
|
|
_.Alt_2, _.RightArrow, CheckThat(() => AssertCursorLeftIs(9)),
|
|
_.Alt_Minus, _.Alt_7, _.RightArrow, CheckThat(() => AssertCursorLeftIs(2))));
|
|
}
|
|
|
|
[SkippableFact]
|
|
public void GotoBrace()
|
|
{
|
|
Skip.IfNot(KeyboardHasCtrlRBracket);
|
|
|
|
TestSetup(KeyMode.Cmd);
|
|
|
|
// Test empty input
|
|
Test("", Keys(_.Ctrl_RBracket));
|
|
|
|
Test("(11)", Keys("(11)", _.LeftArrow, _.Ctrl_RBracket, CheckThat(() => AssertCursorLeftIs(0))));
|
|
Test("$a[11]", Keys("$a[11]", _.LeftArrow, _.Ctrl_RBracket, CheckThat(() => AssertCursorLeftIs(2))));
|
|
Test("{11}", Keys("{11}", _.LeftArrow, _.Ctrl_RBracket, CheckThat(() => AssertCursorLeftIs(0))));
|
|
Test("(11)", Keys("(11)", _.Home, _.Ctrl_RBracket, CheckThat(() => AssertCursorLeftIs(3))));
|
|
Test("$a[11]", Keys("$a[11]", _.Home, _.RightArrow, _.RightArrow, _.Ctrl_RBracket, CheckThat(() => AssertCursorLeftIs(5))));
|
|
Test("{11}", Keys("{11}", _.Home, _.Ctrl_RBracket, CheckThat(() => AssertCursorLeftIs(3))));
|
|
|
|
// Test multiples, make sure we go to the right one.
|
|
Test("((11))", Keys("((11))", _.LeftArrow, _.Ctrl_RBracket, CheckThat(() => AssertCursorLeftIs(0))));
|
|
Test("((11))", Keys("((11))", _.LeftArrow, _.LeftArrow, _.Ctrl_RBracket, CheckThat(() => AssertCursorLeftIs(1))));
|
|
|
|
// Make sure we don't match inside a string
|
|
TestMustDing("", Keys(
|
|
"'()'", _.LeftArrow, _.LeftArrow,
|
|
_.Ctrl_RBracket, CheckThat(() => AssertCursorLeftIs(2)),
|
|
_.Ctrl_c, InputAcceptedNow));
|
|
|
|
foreach (var c in new[] {'(', ')', '{', '}', '[', ']'})
|
|
{
|
|
TestMustDing("", Keys(
|
|
'a', c, _.LeftArrow,
|
|
_.Ctrl_RBracket, CheckThat(() => AssertCursorLeftIs(1)),
|
|
_.Ctrl_c, InputAcceptedNow));
|
|
}
|
|
}
|
|
|
|
[SkippableFact]
|
|
public void CharacterSearch()
|
|
{
|
|
TestSetup(KeyMode.Cmd);
|
|
|
|
Test("cmd1 | cmd2 | cmd3", Keys(
|
|
"cmd1 | cmd2 | cmd3", _.Home,
|
|
_.F3, '|', CheckThat(() => AssertCursorLeftIs(5)),
|
|
_.F3, '|', CheckThat(() => AssertCursorLeftIs(12))));
|
|
}
|
|
|
|
[SkippableFact]
|
|
public void CharacterSearchEmacs()
|
|
{
|
|
Skip.IfNot(KeyboardHasCtrlRBracket);
|
|
|
|
TestSetup(KeyMode.Emacs);
|
|
|
|
Test("cmd1 | cmd2 | cmd3", Keys(
|
|
"cmd1 | cmd2 | cmd3", _.Home,
|
|
_.Ctrl_RBracket, '|', CheckThat(() => AssertCursorLeftIs(5)),
|
|
_.Ctrl_RBracket, '|', CheckThat(() => AssertCursorLeftIs(12)),
|
|
_.End,
|
|
_.Alt_Minus, _.Alt_2, _.Ctrl_RBracket, '|', CheckThat(() => AssertCursorLeftIs(5)),
|
|
_.Home,
|
|
_.Alt_2, _.Ctrl_RBracket, '|', CheckThat(() => AssertCursorLeftIs(12))));
|
|
|
|
TestMustDing("cmd1 | cmd2 | cmd3", Keys(
|
|
"cmd1 | cmd2 | cmd3",
|
|
_.Ctrl_RBracket, 'z'));
|
|
}
|
|
|
|
[SkippableFact]
|
|
public void CharacterSearchApi()
|
|
{
|
|
int i = 0;
|
|
TestSetup(KeyMode.Cmd, new KeyHandler("Ctrl+z",
|
|
(key, count) => PSConsoleReadLine.CharacterSearch(null, i++ == 0 ? (object)'|' : "|")));
|
|
|
|
Test("cmd1 | cmd2 | cmd3", Keys(
|
|
"cmd1 | cmd2 | cmd3",
|
|
_.Home,
|
|
_.Ctrl_z, CheckThat(() => AssertCursorLeftIs(5)),
|
|
_.Ctrl_z, CheckThat(() => AssertCursorLeftIs(12))));
|
|
}
|
|
|
|
[SkippableFact]
|
|
public void CharacterSearchBackward()
|
|
{
|
|
TestSetup(KeyMode.Cmd);
|
|
|
|
Test("cmd1 | cmd2 | cmd3", Keys(
|
|
"cmd1 | cmd2 | cmd3",
|
|
_.Shift_F3, '|', CheckThat(() => AssertCursorLeftIs(12)),
|
|
_.Shift_F3, '|', CheckThat(() => AssertCursorLeftIs(5))));
|
|
}
|
|
|
|
[SkippableFact]
|
|
public void CharacterSearchBackwardEmacs()
|
|
{
|
|
Skip.IfNot(KeyboardHasCtrlRBracket);
|
|
|
|
TestSetup(KeyMode.Emacs);
|
|
|
|
Test("cmd1 | cmd2 | cmd3", Keys(
|
|
"cmd1 | cmd2 | cmd3",
|
|
_.Ctrl_Alt_RBracket, '|', CheckThat(() => AssertCursorLeftIs(12)),
|
|
_.Ctrl_Alt_RBracket, '|', CheckThat(() => AssertCursorLeftIs(5)),
|
|
_.Home,
|
|
_.Alt_Minus, _.Alt_2, _.Ctrl_Alt_RBracket, '|', CheckThat(() => AssertCursorLeftIs(12)),
|
|
_.End,
|
|
_.Alt_2, _.Ctrl_Alt_RBracket, '|', CheckThat(() => AssertCursorLeftIs(5))));
|
|
|
|
TestMustDing("cmd1 | cmd2 | cmd3", Keys(
|
|
"cmd1 | cmd2 | cmd3",
|
|
_.Ctrl_Alt_RBracket, 'z'));
|
|
}
|
|
|
|
[SkippableFact]
|
|
public void CharacterSearchBackwardApi()
|
|
{
|
|
int i = 0;
|
|
TestSetup(KeyMode.Cmd, new KeyHandler("Ctrl+z",
|
|
(key, count) => PSConsoleReadLine.CharacterSearchBackward(null, i++ == 0 ? (object)'|' : "|")));
|
|
|
|
Test("cmd1 | cmd2 | cmd3", Keys(
|
|
"cmd1 | cmd2 | cmd3",
|
|
_.Ctrl_z, CheckThat(() => AssertCursorLeftIs(12)),
|
|
_.Ctrl_z, CheckThat(() => AssertCursorLeftIs(5))));
|
|
}
|
|
}
|
|
}
|