[vi-mode] Undo now leaves the cursor under the position at the start of the deletion (#2045)

This commit is contained in:
Maxime Labelle
2021-09-21 23:04:43 -07:00
committed by GitHub
parent 355bd0894a
commit 1966609701
11 changed files with 280 additions and 101 deletions
+17 -9
View File
@@ -102,7 +102,7 @@ namespace Microsoft.PowerShell
/// </summary>
public static void ForwardDeleteInput(ConsoleKeyInfo? key = null, object arg = null)
{
ForwardDeleteImpl(_singleton._buffer.Length);
ForwardDeleteImpl(_singleton._buffer.Length, ForwardDeleteInput);
}
/// <summary>
@@ -111,7 +111,7 @@ namespace Microsoft.PowerShell
/// </summary>
public static void ForwardDeleteLine(ConsoleKeyInfo? key = null, object arg = null)
{
ForwardDeleteImpl(GetEndOfLogicalLinePos(_singleton._current) + 1);
ForwardDeleteImpl(GetEndOfLogicalLinePos(_singleton._current) + 1, ForwardDeleteLine);
}
/// <summary>
@@ -119,7 +119,7 @@ namespace Microsoft.PowerShell
/// but does not put the deleted text in the kill ring.
/// </summary>
/// <param name="endPosition">0-based offset to one character past the end of the text.</param>
private static void ForwardDeleteImpl(int endPosition)
private static void ForwardDeleteImpl(int endPosition, Action<ConsoleKeyInfo?, object> instigator)
{
var current = _singleton._current;
var buffer = _singleton._buffer;
@@ -128,7 +128,15 @@ namespace Microsoft.PowerShell
{
int length = endPosition - current;
var str = buffer.ToString(current, length);
_singleton.SaveEditItem(EditItemDelete.Create(str, current));
_singleton.SaveEditItem(
EditItemDelete.Create(
str,
current,
instigator,
instigatorArg: null,
!InViEditMode()));
buffer.Remove(current, length);
_singleton.Render();
}
@@ -152,13 +160,13 @@ namespace Microsoft.PowerShell
BackwardDeleteSubstring(position, BackwardDeleteLine);
}
private static void BackwardDeleteSubstring(int position, Action<ConsoleKeyInfo?, object> instigator = null)
private static void BackwardDeleteSubstring(int position, Action<ConsoleKeyInfo?, object> instigator)
{
if (_singleton._current > position)
{
var count = _singleton._current - position;
_singleton.RemoveTextToViRegister(position, count, instigator);
_singleton.RemoveTextToViRegister(position, count, instigator, arg: null, !InViEditMode());
_singleton._current = position;
_singleton.Render();
}
@@ -184,7 +192,7 @@ namespace Microsoft.PowerShell
int startDeleteIndex = _singleton._current - qty;
_singleton.RemoveTextToViRegister(startDeleteIndex, qty, BackwardDeleteChar, arg);
_singleton.RemoveTextToViRegister(startDeleteIndex, qty, BackwardDeleteChar, arg, !InViEditMode());
_singleton._current = startDeleteIndex;
_singleton.Render();
}
@@ -205,7 +213,7 @@ namespace Microsoft.PowerShell
{
qty = Math.Min(qty, _singleton._buffer.Length - _singleton._current);
RemoveTextToViRegister(_current, qty, DeleteChar, qty);
RemoveTextToViRegister(_current, qty, DeleteChar, qty, !InViEditMode());
if (_current >= _buffer.Length)
{
_current = Math.Max(0, _buffer.Length + ViEndOfLineFactor);
+8 -3
View File
@@ -75,7 +75,9 @@ namespace Microsoft.PowerShell
inlineView.OnSuggestionAccepted();
using var _ = prediction.DisableScoped();
Replace(0, _singleton._buffer.Length, inlineView.SuggestionText);
_singleton._current = _singleton._buffer.Length;
Insert(inlineView.SuggestionText.Substring(_singleton._current));
}
}
@@ -105,14 +107,17 @@ namespace Microsoft.PowerShell
// Ignore the visual selection.
_singleton._visualSelectionCommandCount = 0;
int index = _singleton._buffer.Length;
int start = _singleton._buffer.Length;
int index = start;
while (numericArg-- > 0 && index < inlineView.SuggestionText.Length)
{
index = inlineView.FindForwardSuggestionWordPoint(index, _singleton.Options.WordDelimiters);
}
inlineView.OnSuggestionAccepted();
Replace(0, _singleton._buffer.Length, inlineView.SuggestionText.Substring(0, index));
_singleton._current = start;
Insert(inlineView.SuggestionText.Substring(start, index - start));
}
}
+30 -12
View File
@@ -458,6 +458,11 @@ namespace Microsoft.PowerShell
_singleton.ViIndicateInsertMode();
}
/// <summary>
/// Returns true if in Vi edit mode, otherwise false.
/// </summary>
internal static bool InViEditMode() => _singleton.Options.EditMode == EditMode.Vi;
/// <summary>
/// Returns true if in Vi Command mode, otherwise false.
/// </summary>
@@ -621,7 +626,13 @@ namespace Microsoft.PowerShell
if (Char.IsLetter(c))
{
char newChar = Char.IsUpper(c) ? Char.ToLower(c, CultureInfo.CurrentCulture) : char.ToUpper(c, CultureInfo.CurrentCulture);
EditItem delEditItem = EditItemDelete.Create(c.ToString(), _singleton._current);
EditItem delEditItem = EditItemDelete.Create(
c.ToString(),
_singleton._current,
InvertCase,
arg,
moveCursorToEndWhenUndo: false);
EditItem insEditItem = EditItemInsertChar.Create(newChar, _singleton._current);
_singleton.SaveEditItem(GroupedEdit.Create(new List<EditItem>
{
@@ -657,21 +668,22 @@ namespace Microsoft.PowerShell
if (cursor == bufferLength)
--cursor; // if at end of line, swap previous two chars
char current = _singleton._buffer[cursor];
char previous = _singleton._buffer[cursor - 1];
_singleton.SaveEditItem(EditItemSwapCharacters.Create(cursor));
_singleton.SwapCharactersImpl(cursor);
_singleton.StartEditGroup();
_singleton.SaveEditItem(EditItemDelete.Create(_singleton._buffer.ToString(cursor - 1, 2), cursor - 1));
_singleton.SaveEditItem(EditItemInsertChar.Create(current, cursor - 1));
_singleton.SaveEditItem(EditItemInsertChar.Create(previous, cursor));
_singleton.EndEditGroup();
_singleton._buffer[cursor] = previous;
_singleton._buffer[cursor - 1] = current;
_singleton.MoveCursor(Math.Min(cursor + 1, cursorRightLimit));
_singleton.Render();
}
private void SwapCharactersImpl(int cursor)
{
char current = _buffer[cursor];
char previous = _buffer[cursor - 1];
_buffer[cursor] = previous;
_buffer[cursor - 1] = current;
}
/// <summary>
/// Deletes text from the cursor to the first non-blank character of the line.
/// </summary>
@@ -1334,7 +1346,13 @@ namespace Microsoft.PowerShell
{
_singleton._buffer[_singleton._current] = ' ';
_singleton._groupUndoHelper.StartGroup(ViJoinLines, arg);
_singleton.SaveEditItem(EditItemDelete.Create("\n", _singleton._current));
_singleton.SaveEditItem(EditItemDelete.Create(
"\n",
_singleton._current,
ViJoinLines,
arg,
moveCursorToEndWhenUndo: false));
_singleton.SaveEditItem(EditItemInsertChar.Create(' ', _singleton._current));
_singleton._groupUndoHelper.EndGroup();
_singleton.Render();
+14 -2
View File
@@ -65,7 +65,13 @@ namespace Microsoft.PowerShell
{
_singleton.StartEditGroup();
string insStr = _singleton._buffer.ToString(startingCursor, _singleton._current - startingCursor);
_singleton.SaveEditItem(EditItemDelete.Create(deletedStr.ToString(), startingCursor));
_singleton.SaveEditItem(EditItemDelete.Create(
deletedStr.ToString(),
startingCursor,
ViReplaceUntilEsc,
arg,
moveCursorToEndWhenUndo: false));
_singleton.SaveEditItem(EditItemInsertString.Create(insStr, startingCursor));
_singleton.EndEditGroup();
}
@@ -226,7 +232,13 @@ namespace Microsoft.PowerShell
if (_singleton._buffer.Length > 0 && nextKey.KeyStr.Length == 1)
{
_singleton.StartEditGroup();
_singleton.SaveEditItem(EditItemDelete.Create(_singleton._buffer[_singleton._current].ToString(), _singleton._current));
_singleton.SaveEditItem(EditItemDelete.Create(
_singleton._buffer[_singleton._current].ToString(),
_singleton._current,
ReplaceCharInPlace,
arg,
moveCursorToEndWhenUndo: false));
_singleton.SaveEditItem(EditItemInsertString.Create(nextKey.KeyStr, _singleton._current));
_singleton.EndEditGroup();
+44 -5
View File
@@ -258,27 +258,40 @@ namespace Microsoft.PowerShell
private readonly string _deletedString;
private readonly int _deleteStartPosition;
protected EditItemDelete(string str, int position, Action<ConsoleKeyInfo?, object> instigator, object instigatorArg)
// The undo-delete operation will insert some text starting from the '_deleteStartPosition'.
// The '_moveCursorToEndWhenUndo' flag specifies whether the cursor should be moved to the end of the inserted text.
private readonly bool _moveCursorToEndWhenUndo;
protected EditItemDelete(string str, int position, Action<ConsoleKeyInfo?, object> instigator, object instigatorArg, bool moveCursorToEndWhenUndo)
{
_deletedString = str;
_deleteStartPosition = position;
_instigator = instigator;
_instigatorArg = instigatorArg;
_moveCursorToEndWhenUndo = moveCursorToEndWhenUndo;
}
public static EditItem Create(string str, int position, Action<ConsoleKeyInfo?, object> instigator = null, object instigatorArg = null)
public static EditItem Create(
string str,
int position,
Action<ConsoleKeyInfo?, object> instigator = null,
object instigatorArg = null,
bool moveCursorToEndWhenUndo = true)
{
return new EditItemDelete(
str,
position,
instigator,
instigatorArg);
instigatorArg,
moveCursorToEndWhenUndo);
}
public override void Undo()
{
_singleton._buffer.Insert(_deleteStartPosition, _deletedString);
_singleton._current = _deleteStartPosition + _deletedString.Length;
_singleton._current = _moveCursorToEndWhenUndo
? _deleteStartPosition + _deletedString.Length
: _deleteStartPosition;
}
public override void Redo()
@@ -297,7 +310,7 @@ namespace Microsoft.PowerShell
private readonly int _deleteAnchor;
private EditItemDeleteLines(string str, int position, int anchor, Action<ConsoleKeyInfo?, object> instigator, object instigatorArg)
: base(str, position, instigator, instigatorArg)
: base(str, position, instigator, instigatorArg, moveCursorToEndWhenUndo: false)
{
_deleteAnchor = anchor;
}
@@ -314,6 +327,32 @@ namespace Microsoft.PowerShell
}
}
[DebuggerDisplay("SwapCharacters (position: {_swapPosition})")]
class EditItemSwapCharacters : EditItem
{
private readonly int _swapPosition;
private EditItemSwapCharacters(int swapPosition)
{
_swapPosition = swapPosition;
}
public static EditItem Create(int swapPosition)
{
return new EditItemSwapCharacters(swapPosition);
}
public override void Redo()
{
_singleton.SwapCharactersImpl(_swapPosition);
}
public override void Undo()
{
_singleton.SwapCharactersImpl(_swapPosition);
}
}
class GroupedEdit : EditItem
{
internal List<EditItem> _groupedEditItems;
+21 -10
View File
@@ -70,23 +70,34 @@ namespace Microsoft.PowerShell
_viRegister.LinewiseRecord(_buffer.ToString(range.Offset, range.Count));
}
/// <summary>
/// <summary>
/// Remove a portion of text from the buffer, save it to the vi register
/// and also save it to the edit list to support undo.
/// </summary>
/// <param name="start"></param>
/// <param name="count"></param>
/// <param name="instigator"></param>
/// and also save it to the edit list to support undo.
/// </summary>
/// <param name="start"></param>
/// <param name="count"></param>
/// <param name="instigator"></param>
/// <param name="arg"></param>
private void RemoveTextToViRegister(int start, int count, Action<ConsoleKeyInfo?, object> instigator = null, object arg = null)
{
/// <param name="moveCursorToEndWhenUndoDelete">
/// Use 'false' as the default value because this method is used a lot by VI operations,
/// and for VI opeartions, we do NOT want to move the cursor to the end when undoing a
/// deletion.
/// </param>
private void RemoveTextToViRegister(
int start,
int count,
Action<ConsoleKeyInfo?, object> instigator = null,
object arg = null,
bool moveCursorToEndWhenUndoDelete = false)
{
_singleton.SaveToClipboard(start, count);
_singleton.SaveEditItem(EditItemDelete.Create(
_viRegister.RawText,
start,
instigator,
arg));
_singleton._buffer.Remove(start, count);
arg,
moveCursorToEndWhenUndoDelete));
_singleton._buffer.Remove(start, count);
}
/// <summary>
+60 -46
View File
@@ -137,7 +137,7 @@ namespace Test
Test("", Keys(
"0123(567)9ab", _.Escape, "hhh", CheckThat(() => AssertCursorLeftIs(8)),
'c', _.Percent, "45678", _.Escape, CheckThat(() => AssertLineIs("0123456789ab")), CheckThat(() => AssertCursorLeftIs(8)),
'u', CheckThat(() => AssertLineIs("0123(567)9ab")), CheckThat(() => AssertCursorLeftIs(9)),
'u', CheckThat(() => AssertLineIs("0123(567)9ab")), CheckThat(() => AssertCursorLeftIs(4)),
'U'
));
Test("", Keys(
@@ -381,8 +381,8 @@ namespace Test
Test("0123", Keys(
"0123", _.Escape,
"d1h", CheckThat(() => AssertLineIs("013")),
"ud3h", CheckThat(() => AssertLineIs("3")),
"ud4h", CheckThat(() => AssertLineIs("3")),
"u$d3h", CheckThat(() => AssertLineIs("3")),
"u$d4h", CheckThat(() => AssertLineIs("3")),
"u0dl", CheckThat(() => AssertLineIs("123")),
"u0d4l", CheckThat(() => AssertLineIs("")),
"u0d5l", CheckThat(() => AssertLineIs("")),
@@ -432,20 +432,20 @@ namespace Test
Test("nslookup www.google.com", Keys(
"nslookup www", _.Period, "google", _.Period, "com", _.Escape,
"d1b", CheckThat(() => AssertLineIs("nslookup www.google.m")),
"ud2b", CheckThat(() => AssertLineIs("nslookup www.googlem")),
"ud3b", CheckThat(() => AssertLineIs("nslookup www.m")),
"ud4b", CheckThat(() => AssertLineIs("nslookup wwwm")),
"ud5b", CheckThat(() => AssertLineIs("nslookup m")),
"ud6b", CheckThat(() => AssertLineIs("m")),
"ud7b", CheckThat(() => AssertLineIs("m")),
"u$d2b", CheckThat(() => AssertLineIs("nslookup www.googlem")),
"u$d3b", CheckThat(() => AssertLineIs("nslookup www.m")),
"u$d4b", CheckThat(() => AssertLineIs("nslookup wwwm")),
"u$d5b", CheckThat(() => AssertLineIs("nslookup m")),
"u$d6b", CheckThat(() => AssertLineIs("m")),
"u$d7b", CheckThat(() => AssertLineIs("m")),
'u'
));
Test("nslookup www.google.com", Keys(
"nslookup www", _.Period, "google", _.Period, "com", _.Escape,
"d1B", CheckThat(() => AssertLineIs("nslookup m")),
"ud2B", CheckThat(() => AssertLineIs("m")),
"ud3B", CheckThat(() => AssertLineIs("m")),
"u$d2B", CheckThat(() => AssertLineIs("m")),
"u$d3B", CheckThat(() => AssertLineIs("m")),
'u'
));
@@ -529,6 +529,22 @@ namespace Test
));
}
// Defect #1673
[SkippableFact]
public void ViDelete_UndoCursorPosition()
{
TestSetup(KeyMode.Vi);
Test("one", Keys(
"one", _.Escape,
"h", // move back to the 'n' character
"x", CheckThat(() => AssertLineIs("oe")),
// undo
"u", CheckThat(() => AssertCursorLeftIs(1))
));
}
// Defect #1674
[SkippableFact]
public void ViDeleteToCharBack()
@@ -685,9 +701,9 @@ namespace Test
Test("0 2+4 6", Keys(
"0 2+4 6", _.Escape, CheckThat(() => AssertLineIs("0 2+4 6")), CheckThat(() => AssertCursorLeftIs(6)),
"dB", CheckThat(() => AssertLineIs("0 6")), CheckThat(() => AssertCursorLeftIs(2)),
"u", CheckThat(() => AssertLineIs("0 2+4 6")), CheckThat(() => AssertCursorLeftIs(6)),
"2dB", CheckThat(() => AssertLineIs("6")), CheckThat(() => AssertCursorLeftIs(0)),
"u", CheckThat(() => AssertLineIs("0 2+4 6")), CheckThat(() => AssertCursorLeftIs(6))
"u", CheckThat(() => AssertLineIs("0 2+4 6")), CheckThat(() => AssertCursorLeftIs(2)),
"$2dB", CheckThat(() => AssertLineIs("6")), CheckThat(() => AssertCursorLeftIs(0)),
"u", CheckThat(() => AssertLineIs("0 2+4 6")), CheckThat(() => AssertCursorLeftIs(0))
));
Test("0 2+4 6", Keys(
@@ -697,7 +713,7 @@ namespace Test
"u0ldE", CheckThat(() => AssertLineIs("0 6")), CheckThat(() => AssertCursorLeftIs(1)),
"u0l2dE", CheckThat(() => AssertLineIs("0")), CheckThat(() => AssertCursorLeftIs(0)),
"u03dE", CheckThat(() => AssertLineIs("")), CheckThat(() => AssertCursorLeftIs(0)),
"u", CheckThat(() => AssertLineIs("0 2+4 6")), CheckThat(() => AssertCursorLeftIs(6))
"u", CheckThat(() => AssertLineIs("0 2+4 6")), CheckThat(() => AssertCursorLeftIs(0))
));
Test("0 2+4 6", Keys(
@@ -708,7 +724,7 @@ namespace Test
"u0l2dW", CheckThat(() => AssertLineIs("06")), CheckThat(() => AssertCursorLeftIs(1)),
"u0l3dW", CheckThat(() => AssertLineIs("0")), CheckThat(() => AssertCursorLeftIs(0)),
"u03dW", CheckThat(() => AssertLineIs("")), CheckThat(() => AssertCursorLeftIs(0)),
"u", CheckThat(() => AssertLineIs("0 2+4 6")), CheckThat(() => AssertCursorLeftIs(6))
"u", CheckThat(() => AssertLineIs("0 2+4 6")), CheckThat(() => AssertCursorLeftIs(0))
));
}
@@ -738,7 +754,7 @@ namespace Test
Test("(1{3{5)789)b}c", Keys(
"(1{3{5)789)b}c", _.Escape, CheckThat(() => AssertLineIs("(1{3{5)789)b}c")), CheckThat(() => AssertCursorLeftIs(13)),
"hd", _.Percent, CheckThat(() => AssertLineIs("(1{3c")), CheckThat(() => AssertCursorLeftIs(4)),
"u", CheckThat(() => AssertLineIs("(1{3{5)789)b}c")), CheckThat(() => AssertCursorLeftIs(13))
"u", CheckThat(() => AssertLineIs("(1{3{5)789)b}c")), CheckThat(() => AssertCursorLeftIs(4))
));
Test("(1{3[5)7}9)b]", Keys(
@@ -750,13 +766,13 @@ namespace Test
Test("(1{3[5)7}9)b]c", Keys(
"(1{3[5)7}9)b]c", _.Escape, CheckThat(() => AssertLineIs("(1{3[5)7}9)b]c")), CheckThat(() => AssertCursorLeftIs(13)),
"hhhhhd", _.Percent, CheckThat(() => AssertLineIs("(19)b]c")), CheckThat(() => AssertCursorLeftIs(2)),
"u", CheckThat(() => AssertLineIs("(1{3[5)7}9)b]c")), CheckThat(() => AssertCursorLeftIs(9))
"u", CheckThat(() => AssertLineIs("(1{3[5)7}9)b]c")), CheckThat(() => AssertCursorLeftIs(2))
));
Test("(1{3[5)7}9)b]d", Keys(
"(1{3[5)7}9)b]d", _.Escape, CheckThat(() => AssertLineIs("(1{3[5)7}9)b]d")), CheckThat(() => AssertCursorLeftIs(13)),
"h", _.Percent, "d", _.Percent, CheckThat(() => AssertLineIs("(1{3d")), CheckThat(() => AssertCursorLeftIs(4)),
"u", CheckThat(() => AssertLineIs("(1{3[5)7}9)b]d")), CheckThat(() => AssertCursorLeftIs(13))
"u", CheckThat(() => AssertLineIs("(1{3[5)7}9)b]d")), CheckThat(() => AssertCursorLeftIs(4))
));
Test("(1{3[5)7}9)b]", Keys(
@@ -770,7 +786,7 @@ namespace Test
Test("(1{3[5)7}9)b]c", Keys(
"(1{3[5)7}9)b]c", _.Escape, CheckThat(() => AssertLineIs("(1{3[5)7}9)b]c")), CheckThat(() => AssertCursorLeftIs(13)),
"hhhhh", _.Percent, "d", _.Percent, CheckThat(() => AssertLineIs("(19)b]c")), CheckThat(() => AssertCursorLeftIs(2)),
"u", CheckThat(() => AssertLineIs("(1{3[5)7}9)b]c")), CheckThat(() => AssertCursorLeftIs(9))
"u", CheckThat(() => AssertLineIs("(1{3[5)7}9)b]c")), CheckThat(() => AssertCursorLeftIs(2))
));
Test("012 [ 67 ] bc", Keys(
@@ -779,7 +795,7 @@ namespace Test
_.Percent, CheckThat(() => AssertCursorLeftIs(4)),
_.Percent, CheckThat(() => AssertCursorLeftIs(9)),
'd', _.Percent, CheckThat(() => AssertLineIs("012 bc")),
"uh", CheckThat(() => AssertLineIs("012 [ 67 ] bc")), CheckThat(() => AssertCursorLeftIs(9)),
"u", CheckThat(() => AssertLineIs("012 [ 67 ] bc")), CheckThat(() => AssertCursorLeftIs(4)),
'c', _.Percent, "99", _.Escape, CheckThat(() => AssertLineIs("012 99 bc")),
'u'
));
@@ -790,10 +806,9 @@ namespace Test
_.Percent, CheckThat(() => AssertCursorLeftIs(4)),
_.Percent, CheckThat(() => AssertCursorLeftIs(9)),
'd', _.Percent, CheckThat(() => AssertLineIs("012 bc")), CheckThat(() => AssertCursorLeftIs(4)),
'u', CheckThat(() => AssertLineIs("012 { 67 } bc")), CheckThat(() => AssertCursorLeftIs(10)),
'h', _.Percent, CheckThat(() => AssertCursorLeftIs(4)),
'u', CheckThat(() => AssertLineIs("012 { 67 } bc")), CheckThat(() => AssertCursorLeftIs(4)),
'd', _.Percent, CheckThat(() => AssertLineIs("012 bc")), CheckThat(() => AssertCursorLeftIs(4)),
'u', CheckThat(() => AssertCursorLeftIs(10))
'u', CheckThat(() => AssertCursorLeftIs(4))
));
Test("012 ( 67 ) bc", Keys(
@@ -802,10 +817,9 @@ namespace Test
_.Percent, CheckThat(() => AssertCursorLeftIs(4)),
_.Percent, CheckThat(() => AssertCursorLeftIs(9)),
'd', _.Percent, CheckThat(() => AssertLineIs("012 bc")), CheckThat(() => AssertCursorLeftIs(4)),
'u', CheckThat(() => AssertLineIs("012 ( 67 ) bc")), CheckThat(() => AssertCursorLeftIs(10)),
'h', _.Percent, CheckThat(() => AssertCursorLeftIs(4)),
'u', CheckThat(() => AssertLineIs("012 ( 67 ) bc")), CheckThat(() => AssertCursorLeftIs(4)),
'd', _.Percent, CheckThat(() => AssertLineIs("012 bc")), CheckThat(() => AssertCursorLeftIs(4)),
'u', CheckThat(() => AssertCursorLeftIs(10))
'u', CheckThat(() => AssertCursorLeftIs(4))
));
}
@@ -865,9 +879,9 @@ namespace Test
Test("012 45", Keys(
"012 45", _.Escape,
"0cwabc", _.Escape, CheckThat(() => AssertLineIs("abc 45")),
"u", CheckThat(() => AssertLineIs("012 45")), CheckThat(() => AssertCursorLeftIs(4)),
"u", CheckThat(() => AssertLineIs("012 45")), CheckThat(() => AssertCursorLeftIs(0)),
"0cwabc", _.Escape, CheckThat(() => AssertLineIs("abc 45")),
"u", CheckThat(() => AssertCursorLeftIs(4)),
"u", CheckThat(() => AssertCursorLeftIs(0)),
"0cwabc", _.Escape, "wcwef", _.Escape, CheckThat(() => AssertLineIs("abc ef")),
"uu", CheckThat(() => AssertLineIs("012 45")),
"02cwabcdef", _.Escape, CheckThat(() => AssertLineIs("abcdef")),
@@ -1037,25 +1051,25 @@ namespace Test
Test("0123456", Keys(
"0123456", _.Escape, CheckThat(() => AssertLineIs("0123456")),
"0cf6abc", _.Escape, CheckThat(() => AssertLineIs("abc")),
'u', CheckThat(() => AssertLineIs("0123456")), CheckThat(() => AssertCursorLeftIs(6)),
'u', CheckThat(() => AssertLineIs("0123456")), CheckThat(() => AssertCursorLeftIs(0)),
"0cf5abc", _.Escape, CheckThat(() => AssertLineIs("abc6")),
'u', CheckThat(() => AssertLineIs("0123456")), CheckThat(() => AssertCursorLeftIs(6)),
'u', CheckThat(() => AssertLineIs("0123456")), CheckThat(() => AssertCursorLeftIs(0)),
"0lcf6abc", _.Escape, CheckThat(() => AssertLineIs("0abc")),
'u', CheckThat(() => AssertLineIs("0123456")), CheckThat(() => AssertCursorLeftIs(6)),
"cf6abc", _.Escape, CheckThat(() => AssertLineIs("0123456bc")),
'u', CheckThat(() => AssertLineIs("0123456")), CheckThat(() => AssertCursorLeftIs(1)),
"$cf6abc", _.Escape, CheckThat(() => AssertLineIs("0123456bc")),
'u'
));
Test("0123456", Keys(
"0123456", _.Escape, CheckThat(() => AssertLineIs("0123456")),
"cF0abc", _.Escape, CheckThat(() => AssertLineIs("abc6")),
'u', CheckThat(() => AssertLineIs("0123456")), CheckThat(() => AssertCursorLeftIs(6)),
"cF1abc", _.Escape, CheckThat(() => AssertLineIs("0abc6")),
'u', CheckThat(() => AssertLineIs("0123456")), CheckThat(() => AssertCursorLeftIs(6)),
"hcF0abc", _.Escape, CheckThat(() => AssertLineIs("abc56")),
'u', CheckThat(() => AssertLineIs("0123456")), CheckThat(() => AssertCursorLeftIs(5)),
"hcF1abc", _.Escape, CheckThat(() => AssertLineIs("0abc456")),
'u', CheckThat(() => AssertLineIs("0123456")), CheckThat(() => AssertCursorLeftIs(4)),
'u', CheckThat(() => AssertLineIs("0123456")), CheckThat(() => AssertCursorLeftIs(0)),
"$cF1abc", _.Escape, CheckThat(() => AssertLineIs("0abc6")),
'u', CheckThat(() => AssertLineIs("0123456")), CheckThat(() => AssertCursorLeftIs(1)),
"$hcF0abc", _.Escape, CheckThat(() => AssertLineIs("abc56")),
'u', CheckThat(() => AssertLineIs("0123456")), CheckThat(() => AssertCursorLeftIs(0)),
"$hhcF1abc", _.Escape, CheckThat(() => AssertLineIs("0abc456")),
'u', CheckThat(() => AssertLineIs("0123456")), CheckThat(() => AssertCursorLeftIs(1)),
"0cF0abc", _.Escape, CheckThat(() => AssertLineIs("0bc123456")),
'u'
));
@@ -1063,19 +1077,19 @@ namespace Test
Test("0123456", Keys(
"0123456", _.Escape, CheckThat(() => AssertLineIs("0123456")),
"0ct6abc", _.Escape, CheckThat(() => AssertLineIs("abc6")),
'u', CheckThat(() => AssertLineIs("0123456")), CheckThat(() => AssertCursorLeftIs(6)),
'u', CheckThat(() => AssertLineIs("0123456")), CheckThat(() => AssertCursorLeftIs(0)),
"0lct6abc", _.Escape, CheckThat(() => AssertLineIs("0abc6")),
'u', CheckThat(() => AssertLineIs("0123456")), CheckThat(() => AssertCursorLeftIs(6)),
"ct6abc", _.Escape, CheckThat(() => AssertLineIs("0123456bc")),
'u', CheckThat(() => AssertLineIs("0123456")), CheckThat(() => AssertCursorLeftIs(1)),
"$ct6abc", _.Escape, CheckThat(() => AssertLineIs("0123456bc")),
'u'
));
Test("0123456", Keys(
"0123456", _.Escape, CheckThat(() => AssertLineIs("0123456")),
"cT1abc", _.Escape, CheckThat(() => AssertLineIs("01abc6")),
'u', CheckThat(() => AssertLineIs("0123456")), CheckThat(() => AssertCursorLeftIs(6)),
"hcT1abc", _.Escape, CheckThat(() => AssertLineIs("01abc56")),
'u', CheckThat(() => AssertLineIs("0123456")), CheckThat(() => AssertCursorLeftIs(5)),
'u', CheckThat(() => AssertLineIs("0123456")), CheckThat(() => AssertCursorLeftIs(2)),
"$hcT1abc", _.Escape, CheckThat(() => AssertLineIs("01abc56")),
'u', CheckThat(() => AssertLineIs("0123456")), CheckThat(() => AssertCursorLeftIs(2)),
"0cT0abc", _.Escape, CheckThat(() => AssertLineIs("0bc123456")),
'u'
));
+31 -1
View File
@@ -200,6 +200,36 @@ namespace Test
Test("exit", Keys("foo", _.Home, Enumerable.Repeat(_.Ctrl_d, 4), InputAcceptedNow));
}
[SkippableFact]
public void SelectAndDelete()
{
TestSetup(KeyMode.Cmd);
Test("abcde", Keys(
"abcde",
CheckThat(() => AssertCursorLeftIs(5)),
_.Shift_LeftArrow, _.Shift_LeftArrow, _.Shift_LeftArrow,
_.Backspace,
CheckThat(() => AssertLineIs("ab")),
CheckThat(() => AssertCursorLeftIs(2)),
_.Ctrl_z,
CheckThat(() => AssertLineIs("abcde")),
CheckThat(() => AssertCursorLeftIs(5))));
Test("abcde", Keys(
"abcde", _.Home,
CheckThat(() => AssertCursorLeftIs(0)),
_.RightArrow, _.RightArrow,
CheckThat(() => AssertCursorLeftIs(2)),
_.Shift_RightArrow, _.Shift_RightArrow,
_.Delete,
CheckThat(() => AssertLineIs("abe")),
CheckThat(() => AssertCursorLeftIs(2)),
_.Ctrl_z,
CheckThat(() => AssertLineIs("abcde")),
CheckThat(() => AssertCursorLeftIs(4))));
}
[SkippableFact]
public void SwapCharacters()
{
@@ -212,7 +242,7 @@ namespace Test
Test("abc", Keys(
"abc", CheckThat(() => AssertLineIs("abc")),
_.Ctrl_t, CheckThat(() => AssertLineIs("acb")),
_.Ctrl_Underbar
_.Ctrl_Underbar, CheckThat(() => AssertCursorLeftIs(3))
));
Test("abcd", Keys(
+30
View File
@@ -364,6 +364,36 @@ namespace Test
));
}
[SkippableFact]
public void ViDefect2408()
{
TestSetup(KeyMode.Vi);
using var disp = SetPrediction(PredictionSource.History, PredictionViewStyle.InlineView);
SetHistory("echo -bar");
Test("ech", Keys(
"abcd",
CheckThat(() => AssertScreenIs(1,
TokenClassification.Command, "abcd")),
_.Escape, 'S',
CheckThat(() => AssertLineIs(string.Empty)),
CheckThat(() => AssertCursorLeftIs(0)),
"ech",
CheckThat(() => AssertScreenIs(1,
TokenClassification.Command, "ech",
TokenClassification.InlinePrediction, "o -bar")),
_.RightArrow,
CheckThat(() => AssertScreenIs(1,
TokenClassification.Command, "echo",
TokenClassification.None, ' ',
TokenClassification.Parameter, "-bar")),
CheckThat(() => AssertCursorLeftIs(9)),
_.Ctrl_z,
CheckThat(() => AssertScreenIs(1,
TokenClassification.Command, "ech",
TokenClassification.InlinePrediction, "o -bar"))));
}
private const uint MiniSessionId = 56;
private static readonly Guid predictorId_1 = Guid.Parse("b45b5fbe-90fa-486c-9c87-e7940fdd6273");
private static readonly Guid predictorId_2 = Guid.Parse("74a86463-033b-44a3-b386-41ee191c94be");
+22 -10
View File
@@ -620,25 +620,25 @@ namespace Test
Test("", Keys(
"abcdefg", _.Escape, CheckThat(() => AssertLineIs("abcdefg")),
"0dfg", CheckThat(() => AssertLineIs("")),
'u', CheckThat(() => AssertLineIs("abcdefg")), CheckThat(() => AssertCursorLeftIs(6)),
'u', CheckThat(() => AssertLineIs("abcdefg")), CheckThat(() => AssertCursorLeftIs(0)),
"0dff", CheckThat(() => AssertLineIs("g")),
'u', CheckThat(() => AssertLineIs("abcdefg")), CheckThat(() => AssertCursorLeftIs(6)),
'u', CheckThat(() => AssertLineIs("abcdefg")), CheckThat(() => AssertCursorLeftIs(0)),
"0dfg"
));
Test("g", Keys(
Test("bcdefg", Keys(
"abcdefg", _.Escape, CheckThat(() => AssertLineIs("abcdefg")),
"dFa", _.Escape, CheckThat(() => AssertLineIs("g")),
'u', CheckThat(() => AssertCursorLeftIs(6)),
"dFb", CheckThat(() => AssertLineIs("ag")),
'u', CheckThat(() => AssertCursorLeftIs(6)),
'u', CheckThat(() => AssertCursorLeftIs(0)),
"$dFb", CheckThat(() => AssertLineIs("ag")),
'u', CheckThat(() => AssertCursorLeftIs(1)),
"dFa"
));
Test("0123456", Keys(
"0123456", _.Escape, CheckThat(() => AssertLineIs("0123456")),
"0dt6", CheckThat(() => AssertLineIs("6")),
'u', CheckThat(() => AssertLineIs("0123456")), CheckThat(() => AssertCursorLeftIs(6)),
'u', CheckThat(() => AssertLineIs("0123456")), CheckThat(() => AssertCursorLeftIs(0)),
"0dt5", CheckThat(() => AssertLineIs("56")),
'u', CheckThat(() => AssertLineIs("0123456")),
"0ldt6", CheckThat(() => AssertLineIs("06")),
@@ -650,9 +650,9 @@ namespace Test
Test("0123456", Keys(
"0123456", _.Escape, CheckThat(() => AssertLineIs("0123456")),
"dT0", CheckThat(() => AssertLineIs("06")),
'u', CheckThat(() => AssertLineIs("0123456")), CheckThat(() => AssertCursorLeftIs(6)),
"hdT0", CheckThat(() => AssertLineIs("056")),
'u', CheckThat(() => AssertLineIs("0123456")), CheckThat(() => AssertCursorLeftIs(5)),
'u', CheckThat(() => AssertLineIs("0123456")), CheckThat(() => AssertCursorLeftIs(1)),
"$hdT0", CheckThat(() => AssertLineIs("056")),
'u', CheckThat(() => AssertLineIs("0123456")), CheckThat(() => AssertCursorLeftIs(1)),
"0dT0"
));
}
@@ -666,5 +666,17 @@ namespace Test
_.Escape, "kjw"
));
}
[SkippableFact]
public void ViDefect1673()
{
TestSetup(KeyMode.Vi);
Test("one", Keys(
"one", _.Escape, _.D0,
_.x, CheckThat(() => AssertLineIs("ne")),
_.u, CheckThat(() => AssertCursorLeftIs(0))
));
}
}
}
+3 -3
View File
@@ -49,7 +49,7 @@ namespace Test
_.Escape, CheckThat(() => AssertCursorLeftIs(5)),
'b', CheckThat(() => AssertCursorLeftIs(4)),
"dw", CheckThat(() => AssertLineIs("test")),
"ubcw", CheckThat(() => AssertLineIs("test")),
"ulbcw", CheckThat(() => AssertLineIs("test")),
"[]", _.Escape, CheckThat(() => AssertLineIs("test[]")),
'u'
));
@@ -59,8 +59,8 @@ namespace Test
CheckThat(() => AssertLineIs(@"vim .\PSReadLine\VisualEditing.vi.cs")),
_.Escape, "Bll", CheckThat(() => AssertCursorLeftIs(6)),
"cw", _.Escape, CheckThat(() => AssertCursorLeftIs(5)), CheckThat(() => AssertLineIs(@"vim .\\VisualEditing.vi.cs")),
'u', CheckThat(() => AssertCursorLeftIs(16)), CheckThat(() => AssertLineIs(@"vim .\PSReadLine\VisualEditing.vi.cs")),
"bcwxx", _.Escape, CheckThat(() => AssertCursorLeftIs(7))
'u', CheckThat(() => AssertCursorLeftIs(6)), CheckThat(() => AssertLineIs(@"vim .\PSReadLine\VisualEditing.vi.cs")),
"cwxx", _.Escape, CheckThat(() => AssertCursorLeftIs(7))
));
Test("$response.Headers['location']", Keys(