Skip to content

Commit 47fb957

Browse files
authored
Make d0 to delete to the start of the current logical line in a multiline buffer in VI mode (#2002)
1 parent 7119664 commit 47fb957

9 files changed

+156
-26
lines changed

PSReadLine/BasicEditing.cs

Lines changed: 45 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -97,16 +97,36 @@ public static void CancelLine(ConsoleKeyInfo? key = null, object arg = null)
9797
}
9898

9999
/// <summary>
100-
/// Like ForwardKillLine - deletes text from the point to the end of the line,
100+
/// Like KillLine - deletes text from the point to the end of the input,
101+
/// but does not put the deleted text in the kill ring.
102+
/// </summary>
103+
public static void ForwardDeleteInput(ConsoleKeyInfo? key = null, object arg = null)
104+
{
105+
ForwardDeleteImpl(_singleton._buffer.Length);
106+
}
107+
108+
/// <summary>
109+
/// Deletes text from the point to the end of the current logical line,
101110
/// but does not put the deleted text in the kill ring.
102111
/// </summary>
103112
public static void ForwardDeleteLine(ConsoleKeyInfo? key = null, object arg = null)
113+
{
114+
ForwardDeleteImpl(GetEndOfLogicalLinePos(_singleton._current) + 1);
115+
}
116+
117+
/// <summary>
118+
/// Deletes text from the cursor position to the specified end position
119+
/// but does not put the deleted text in the kill ring.
120+
/// </summary>
121+
/// <param name="endPosition">0-based offset to one character past the end of the text.</param>
122+
private static void ForwardDeleteImpl(int endPosition)
104123
{
105124
var current = _singleton._current;
106125
var buffer = _singleton._buffer;
107-
if (buffer.Length > 0 && current < buffer.Length)
126+
127+
if (buffer.Length > 0 && current < endPosition)
108128
{
109-
int length = buffer.Length - current;
129+
int length = endPosition - current;
110130
var str = buffer.ToString(current, length);
111131
_singleton.SaveEditItem(EditItemDelete.Create(str, current));
112132
buffer.Remove(current, length);
@@ -115,17 +135,33 @@ public static void ForwardDeleteLine(ConsoleKeyInfo? key = null, object arg = nu
115135
}
116136

117137
/// <summary>
118-
/// Like BackwardKillLine - deletes text from the point to the start of the line,
138+
/// Like BackwardKillInput - deletes text from the point to the start of the input,
139+
/// but does not put the deleted text in the kill ring.
140+
public static void BackwardDeleteInput(ConsoleKeyInfo? key = null, object arg = null)
141+
{
142+
BackwardDeleteSubstring(0, BackwardDeleteInput);
143+
}
144+
145+
/// <summary>
146+
/// Like BackwardKillLine - deletes text from the point to the start of the logical line,
119147
/// but does not put the deleted text in the kill ring.
120148
/// </summary>
121149
public static void BackwardDeleteLine(ConsoleKeyInfo? key = null, object arg = null)
122150
{
123-
if (_singleton._current > 0)
151+
var position = GetBeginningOfLinePos(_singleton._current);
152+
BackwardDeleteSubstring(position, BackwardDeleteLine);
153+
}
154+
155+
private static void BackwardDeleteSubstring(int position, Action<ConsoleKeyInfo?, object> instigator = null)
156+
{
157+
if (_singleton._current > position)
124158
{
125-
_clipboard.Record(_singleton._buffer, 0, _singleton._current);
126-
_singleton.SaveEditItem(EditItemDelete.Create(_clipboard, 0));
127-
_singleton._buffer.Remove(0, _singleton._current);
128-
_singleton._current = 0;
159+
var count = _singleton._current - position;
160+
161+
_clipboard.Record(_singleton._buffer, position, count);
162+
_singleton.SaveEditItem(EditItemDelete.Create(_clipboard, position, instigator));
163+
_singleton._buffer.Remove(position, count);
164+
_singleton._current = position;
129165
_singleton.Render();
130166
}
131167
}

PSReadLine/KeyBindings.cs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ void SetDefaultWindowsBindings()
209209
{ Keys.CtrlY, MakeKeyHandler(Redo, "Redo") },
210210
{ Keys.CtrlZ, MakeKeyHandler(Undo, "Undo") },
211211
{ Keys.CtrlBackspace, MakeKeyHandler(BackwardKillWord, "BackwardKillWord") },
212-
{ Keys.CtrlHome, MakeKeyHandler(BackwardDeleteLine, "BackwardDeleteLine") },
212+
{ Keys.CtrlHome, MakeKeyHandler(BackwardDeleteInput, "BackwardDeleteInput") },
213213
{ Keys.CtrlRBracket, MakeKeyHandler(GotoBrace, "GotoBrace") },
214214
{ Keys.CtrlAltQuestion, MakeKeyHandler(ShowKeyBindings, "ShowKeyBindings") },
215215
{ Keys.AltPeriod, MakeKeyHandler(YankLastArg, "YankLastArg") },
@@ -242,7 +242,7 @@ void SetDefaultWindowsBindings()
242242
_dispatchTable.Add(Keys.CtrlSpace, MakeKeyHandler(MenuComplete, "MenuComplete"));
243243
_dispatchTable.Add(Keys.AltF7, MakeKeyHandler(ClearHistory, "ClearHistory"));
244244
_dispatchTable.Add(Keys.CtrlDelete, MakeKeyHandler(KillWord, "KillWord"));
245-
_dispatchTable.Add(Keys.CtrlEnd, MakeKeyHandler(ForwardDeleteLine, "ForwardDeleteLine"));
245+
_dispatchTable.Add(Keys.CtrlEnd, MakeKeyHandler(ForwardDeleteInput, "ForwardDeleteInput"));
246246
_dispatchTable.Add(Keys.CtrlH, MakeKeyHandler(BackwardDeleteChar,"BackwardDeleteChar"));
247247

248248
// PageUp/PageDown and CtrlPageUp/CtrlPageDown bindings are supported on Windows only because they depend on the
@@ -294,7 +294,7 @@ void SetDefaultEmacsBindings()
294294
{ Keys.CtrlR, MakeKeyHandler(ReverseSearchHistory, "ReverseSearchHistory") },
295295
{ Keys.CtrlS, MakeKeyHandler(ForwardSearchHistory, "ForwardSearchHistory") },
296296
{ Keys.CtrlT, MakeKeyHandler(SwapCharacters, "SwapCharacters") },
297-
{ Keys.CtrlU, MakeKeyHandler(BackwardKillLine, "BackwardKillLine") },
297+
{ Keys.CtrlU, MakeKeyHandler(BackwardKillInput, "BackwardKillInput") },
298298
{ Keys.CtrlX, MakeKeyHandler(Chord, "ChordFirstKey") },
299299
{ Keys.CtrlW, MakeKeyHandler(UnixWordRubout, "UnixWordRubout") },
300300
{ Keys.CtrlY, MakeKeyHandler(Yank, "Yank") },
@@ -369,7 +369,7 @@ void SetDefaultEmacsBindings()
369369
// Ctrl+X,<key> table
370370
[Keys.CtrlX] = new Dictionary<PSKeyInfo, KeyHandler>
371371
{
372-
{ Keys.Backspace, MakeKeyHandler(BackwardKillLine, "BackwardKillLine") },
372+
{ Keys.Backspace, MakeKeyHandler(BackwardKillInput, "BackwardKillInput") },
373373
{ Keys.CtrlE, MakeKeyHandler(ViEditVisually, "ViEditVisually") },
374374
{ Keys.CtrlU, MakeKeyHandler(Undo, "Undo") },
375375
{ Keys.CtrlX, MakeKeyHandler(ExchangePointAndMark, "ExchangePointAndMark") },
@@ -388,9 +388,11 @@ public static KeyHandlerGroup GetDisplayGrouping(string function)
388388
case nameof(AcceptAndGetNext):
389389
case nameof(AcceptLine):
390390
case nameof(AddLine):
391+
case nameof(BackwardDeleteInput):
391392
case nameof(BackwardDeleteChar):
392393
case nameof(BackwardDeleteLine):
393394
case nameof(BackwardDeleteWord):
395+
case nameof(BackwardKillInput):
394396
case nameof(BackwardKillLine):
395397
case nameof(BackwardKillWord):
396398
case nameof(CancelLine):
@@ -408,6 +410,7 @@ public static KeyHandlerGroup GetDisplayGrouping(string function)
408410
case nameof(DeletePreviousLines):
409411
case nameof(DeleteToEnd):
410412
case nameof(DeleteWord):
413+
case nameof(ForwardDeleteInput):
411414
case nameof(ForwardDeleteLine):
412415
case nameof(InsertLineAbove):
413416
case nameof(InsertLineBelow):

PSReadLine/KeyBindings.vi.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -72,16 +72,16 @@ private void SetDefaultViBindings()
7272
{ Keys.CtrlSpace, MakeKeyHandler(PossibleCompletions, "PossibleCompletions") },
7373
{ Keys.Tab, MakeKeyHandler(ViTabCompleteNext, "ViTabCompleteNext") },
7474
{ Keys.ShiftTab, MakeKeyHandler(ViTabCompletePrevious, "ViTabCompletePrevious") },
75-
{ Keys.CtrlU, MakeKeyHandler(BackwardDeleteLine, "BackwardDeleteLine") },
75+
{ Keys.CtrlU, MakeKeyHandler(BackwardDeleteInput, "BackwardDeleteInput") },
7676
{ Keys.CtrlV, MakeKeyHandler(Paste, "Paste") },
7777
{ Keys.CtrlC, MakeKeyHandler(CancelLine, "CancelLine") },
7878
{ Keys.CtrlL, MakeKeyHandler(ClearScreen, "ClearScreen") },
7979
{ Keys.CtrlT, MakeKeyHandler(SwapCharacters, "SwapCharacters") },
8080
{ Keys.CtrlY, MakeKeyHandler(Redo, "Redo") },
8181
{ Keys.CtrlZ, MakeKeyHandler(Undo, "Undo") },
8282
{ Keys.CtrlBackspace, MakeKeyHandler(BackwardKillWord, "BackwardKillWord") },
83-
{ Keys.CtrlEnd, MakeKeyHandler(ForwardDeleteLine, "ForwardDeleteLine") },
84-
{ Keys.CtrlHome, MakeKeyHandler(BackwardDeleteLine, "BackwardDeleteLine") },
83+
{ Keys.CtrlEnd, MakeKeyHandler(ForwardDeleteInput, "ForwardDeleteInput") },
84+
{ Keys.CtrlHome, MakeKeyHandler(BackwardDeleteInput, "BackwardDeleteInput") },
8585
{ Keys.CtrlRBracket, MakeKeyHandler(GotoBrace, "GotoBrace") },
8686
{ Keys.F3, MakeKeyHandler(CharacterSearch, "CharacterSearch") },
8787
{ Keys.ShiftF3, MakeKeyHandler(CharacterSearchBackward,"CharacterSearchBackward") },
@@ -120,13 +120,13 @@ private void SetDefaultViBindings()
120120
{ Keys.CtrlC, MakeKeyHandler(CancelLine, "CancelLine") },
121121
{ Keys.CtrlL, MakeKeyHandler(ClearScreen, "ClearScreen") },
122122
{ Keys.CtrlT, MakeKeyHandler(SwapCharacters, "SwapCharacters") },
123-
{ Keys.CtrlU, MakeKeyHandler(BackwardDeleteLine, "BackwardDeleteLine") },
123+
{ Keys.CtrlU, MakeKeyHandler(BackwardDeleteInput, "BackwardDeleteInput") },
124124
{ Keys.CtrlW, MakeKeyHandler(BackwardDeleteWord, "BackwardDeleteWord") },
125125
{ Keys.CtrlY, MakeKeyHandler(Redo, "Redo") },
126126
{ Keys.CtrlZ, MakeKeyHandler(Undo, "Undo") },
127127
{ Keys.CtrlBackspace, MakeKeyHandler(BackwardKillWord, "BackwardKillWord") },
128-
{ Keys.CtrlEnd, MakeKeyHandler(ForwardDeleteLine, "ForwardDeleteLine") },
129-
{ Keys.CtrlHome, MakeKeyHandler(BackwardDeleteLine, "BackwardDeleteLine") },
128+
{ Keys.CtrlEnd, MakeKeyHandler(ForwardDeleteInput, "ForwardDeleteInput") },
129+
{ Keys.CtrlHome, MakeKeyHandler(BackwardDeleteInput, "BackwardDeleteInput") },
130130
{ Keys.CtrlRBracket, MakeKeyHandler(GotoBrace, "GotoBrace") },
131131
{ Keys.F3, MakeKeyHandler(CharacterSearch, "CharacterSearch") },
132132
{ Keys.ShiftF3, MakeKeyHandler(CharacterSearchBackward, "CharacterSearchBackward") },

PSReadLine/KillYank.cs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,11 +117,21 @@ public static void KillLine(ConsoleKeyInfo? key = null, object arg = null)
117117
/// Clear the input from the start of the input to the cursor. The cleared text is placed
118118
/// in the kill ring.
119119
/// </summary>
120-
public static void BackwardKillLine(ConsoleKeyInfo? key = null, object arg = null)
120+
public static void BackwardKillInput(ConsoleKeyInfo? key = null, object arg = null)
121121
{
122122
_singleton.Kill(0, _singleton._current, true);
123123
}
124124

125+
/// <summary>
126+
/// Clear the input from the start of the current logical line to the cursor. The cleared text is placed
127+
/// in the kill ring.
128+
/// </summary>
129+
public static void BackwardKillLine(ConsoleKeyInfo? key = null, object arg = null)
130+
{
131+
var start = GetBeginningOfLinePos(_singleton._current);
132+
_singleton.Kill(start, _singleton._current, true);
133+
}
134+
125135
/// <summary>
126136
/// Clear the input from the cursor to the end of the current word. If the cursor
127137
/// is between words, the input is cleared from the cursor to the end of the next word.

PSReadLine/PSReadLineResources.Designer.cs

Lines changed: 28 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

PSReadLine/PSReadLineResources.resx

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -129,11 +129,17 @@
129129
<data name="BackwardDeleteCharDescription" xml:space="preserve">
130130
<value>Delete the character before the cursor</value>
131131
</data>
132+
<data name="BackwardDeleteInputDescription" xml:space="preserve">
133+
<value>Delete text from the cursor to the start of the input</value>
134+
</data>
132135
<data name="BackwardDeleteLineDescription" xml:space="preserve">
133-
<value>Delete text from the cursor to the start of the line</value>
136+
<value>Delete text from the cursor to the start of the current logical line</value>
137+
</data>
138+
<data name="BackwardKillInputDescription" xml:space="preserve">
139+
<value>Move the text from the cursor to the beginning of the input to the kill ring</value>
134140
</data>
135141
<data name="BackwardKillLineDescription" xml:space="preserve">
136-
<value>Move the text from the cursor to the beginning of the line to the kill ring</value>
142+
<value>Move the text from the start of the current logical line to the cursor to the kill ring</value>
137143
</data>
138144
<data name="BeginningOfHistoryDescription" xml:space="preserve">
139145
<value>Move to the first item in the history</value>
@@ -180,8 +186,11 @@
180186
<data name="ForwardCharDescription" xml:space="preserve">
181187
<value>Move the cursor forward one character</value>
182188
</data>
189+
<data name="ForwardDeleteInputDescription" xml:space="preserve">
190+
<value>Delete text from the cursor to the end of the input</value>
191+
</data>
183192
<data name="ForwardDeleteLineDescription" xml:space="preserve">
184-
<value>Delete text from the cursor to the end of the line</value>
193+
<value>Delete text from the cursor to the end of the current logical line</value>
185194
</data>
186195
<data name="ShellForwardWordDescription" xml:space="preserve">
187196
<value>Move the cursor to the beginning of the next token or end of line</value>

test/BasicEditingTest.VI.cs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -570,6 +570,26 @@ public void ViDeleteToEnd()
570570
));
571571
}
572572

573+
[SkippableFact]
574+
public void ViBackwardDeleteLine()
575+
{
576+
TestSetup(KeyMode.Vi);
577+
578+
int continuationPrefixLength = PSConsoleReadLineOptions.DefaultContinuationPrompt.Length;
579+
580+
Test("\"\nsome words\n\"", Keys(
581+
582+
_.DQuote, _.Enter,
583+
" this is a line with some words", _.Enter,
584+
_.DQuote, _.Escape,
585+
"k6W",
586+
CheckThat(() => AssertCursorLeftIs(continuationPrefixLength + 23)),
587+
// delete from first non blank of line
588+
"d0",
589+
CheckThat(() => AssertCursorLeftIs(continuationPrefixLength))
590+
));
591+
}
592+
573593
[SkippableFact]
574594
public void ViDeleteLineToFirstChar()
575595
{

test/BasicEditingTest.cs

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ public void CancelLine()
7373
}
7474

7575
[SkippableFact]
76-
public void ForwardDeleteLine()
76+
public void ForwardDeleteInput()
7777
{
7878
ConsoleKeyInfo deleteToEnd;
7979
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
@@ -98,7 +98,22 @@ public void ForwardDeleteLine()
9898
}
9999

100100
[SkippableFact]
101-
public void BackwardDeleteLine()
101+
public void ForwardDeleteLine()
102+
{
103+
TestSetup(KeyMode.Emacs);
104+
105+
PSConsoleReadLine.SetKeyHandler(new[] { "Shift+Tab" }, PSConsoleReadLine.ForwardDeleteLine, "", "");
106+
107+
Test("\"H\nWorld\"", Keys(
108+
_.DQuote, "Hello", _.Enter,
109+
"World", _.DQuote,
110+
_.Home, _.Home, _.RightArrow, _.RightArrow,
111+
_.Shift_Tab // delete to the end of the current logical line
112+
));
113+
}
114+
115+
[SkippableFact]
116+
public void BackwardDeleteInput()
102117
{
103118
TestSetup(KeyMode.Cmd);
104119

test/KillYankTest.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,16 @@ public void BackwardKillLine()
116116
{
117117
TestSetup(KeyMode.Emacs);
118118

119+
PSConsoleReadLine.SetKeyHandler(new[] { "Shift+Tab" }, PSConsoleReadLine.BackwardKillLine, "", "");
120+
121+
Test("", Keys("dir", _.Shift_Tab));
122+
}
123+
124+
[SkippableFact]
125+
public void BackwardKillInput()
126+
{
127+
TestSetup(KeyMode.Emacs);
128+
119129
// Kill whole line
120130
// Check killed text by yanking
121131
Test("ls", Keys("dir", _.Ctrl_u, "ls"));

0 commit comments

Comments
 (0)