Files

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))));
}
}
}