diff --git a/PSReadLine/BasicEditing.cs b/PSReadLine/BasicEditing.cs
index e7236a21..33405a88 100644
--- a/PSReadLine/BasicEditing.cs
+++ b/PSReadLine/BasicEditing.cs
@@ -97,16 +97,36 @@ public static void CancelLine(ConsoleKeyInfo? key = null, object arg = null)
}
///
- /// Like ForwardKillLine - deletes text from the point to the end of the line,
+ /// Like KillLine - deletes text from the point to the end of the input,
+ /// but does not put the deleted text in the kill ring.
+ ///
+ public static void ForwardDeleteInput(ConsoleKeyInfo? key = null, object arg = null)
+ {
+ ForwardDeleteImpl(_singleton._buffer.Length);
+ }
+
+ ///
+ /// Deletes text from the point to the end of the current logical line,
/// but does not put the deleted text in the kill ring.
///
public static void ForwardDeleteLine(ConsoleKeyInfo? key = null, object arg = null)
+ {
+ ForwardDeleteImpl(GetEndOfLogicalLinePos(_singleton._current) + 1);
+ }
+
+ ///
+ /// Deletes text from the cursor position to the specified end position
+ /// but does not put the deleted text in the kill ring.
+ ///
+ /// 0-based offset to one character past the end of the text.
+ private static void ForwardDeleteImpl(int endPosition)
{
var current = _singleton._current;
var buffer = _singleton._buffer;
- if (buffer.Length > 0 && current < buffer.Length)
+
+ if (buffer.Length > 0 && current < endPosition)
{
- int length = buffer.Length - current;
+ int length = endPosition - current;
var str = buffer.ToString(current, length);
_singleton.SaveEditItem(EditItemDelete.Create(str, current));
buffer.Remove(current, length);
@@ -115,17 +135,33 @@ public static void ForwardDeleteLine(ConsoleKeyInfo? key = null, object arg = nu
}
///
- /// Like BackwardKillLine - deletes text from the point to the start of the line,
+ /// Like BackwardKillInput - deletes text from the point to the start of the input,
+ /// but does not put the deleted text in the kill ring.
+ public static void BackwardDeleteInput(ConsoleKeyInfo? key = null, object arg = null)
+ {
+ BackwardDeleteSubstring(0, BackwardDeleteInput);
+ }
+
+ ///
+ /// Like BackwardKillLine - deletes text from the point to the start of the logical line,
/// but does not put the deleted text in the kill ring.
///
public static void BackwardDeleteLine(ConsoleKeyInfo? key = null, object arg = null)
{
- if (_singleton._current > 0)
+ var position = GetBeginningOfLinePos(_singleton._current);
+ BackwardDeleteSubstring(position, BackwardDeleteLine);
+ }
+
+ private static void BackwardDeleteSubstring(int position, Action instigator = null)
+ {
+ if (_singleton._current > position)
{
- _clipboard.Record(_singleton._buffer, 0, _singleton._current);
- _singleton.SaveEditItem(EditItemDelete.Create(_clipboard, 0));
- _singleton._buffer.Remove(0, _singleton._current);
- _singleton._current = 0;
+ var count = _singleton._current - position;
+
+ _clipboard.Record(_singleton._buffer, position, count);
+ _singleton.SaveEditItem(EditItemDelete.Create(_clipboard, position, instigator));
+ _singleton._buffer.Remove(position, count);
+ _singleton._current = position;
_singleton.Render();
}
}
diff --git a/PSReadLine/KeyBindings.cs b/PSReadLine/KeyBindings.cs
index edd049a5..b9691d2b 100644
--- a/PSReadLine/KeyBindings.cs
+++ b/PSReadLine/KeyBindings.cs
@@ -209,7 +209,7 @@ void SetDefaultWindowsBindings()
{ Keys.CtrlY, MakeKeyHandler(Redo, "Redo") },
{ Keys.CtrlZ, MakeKeyHandler(Undo, "Undo") },
{ Keys.CtrlBackspace, MakeKeyHandler(BackwardKillWord, "BackwardKillWord") },
- { Keys.CtrlHome, MakeKeyHandler(BackwardDeleteLine, "BackwardDeleteLine") },
+ { Keys.CtrlHome, MakeKeyHandler(BackwardDeleteInput, "BackwardDeleteInput") },
{ Keys.CtrlRBracket, MakeKeyHandler(GotoBrace, "GotoBrace") },
{ Keys.CtrlAltQuestion, MakeKeyHandler(ShowKeyBindings, "ShowKeyBindings") },
{ Keys.AltPeriod, MakeKeyHandler(YankLastArg, "YankLastArg") },
@@ -242,7 +242,7 @@ void SetDefaultWindowsBindings()
_dispatchTable.Add(Keys.CtrlSpace, MakeKeyHandler(MenuComplete, "MenuComplete"));
_dispatchTable.Add(Keys.AltF7, MakeKeyHandler(ClearHistory, "ClearHistory"));
_dispatchTable.Add(Keys.CtrlDelete, MakeKeyHandler(KillWord, "KillWord"));
- _dispatchTable.Add(Keys.CtrlEnd, MakeKeyHandler(ForwardDeleteLine, "ForwardDeleteLine"));
+ _dispatchTable.Add(Keys.CtrlEnd, MakeKeyHandler(ForwardDeleteInput, "ForwardDeleteInput"));
_dispatchTable.Add(Keys.CtrlH, MakeKeyHandler(BackwardDeleteChar,"BackwardDeleteChar"));
// PageUp/PageDown and CtrlPageUp/CtrlPageDown bindings are supported on Windows only because they depend on the
@@ -294,7 +294,7 @@ void SetDefaultEmacsBindings()
{ Keys.CtrlR, MakeKeyHandler(ReverseSearchHistory, "ReverseSearchHistory") },
{ Keys.CtrlS, MakeKeyHandler(ForwardSearchHistory, "ForwardSearchHistory") },
{ Keys.CtrlT, MakeKeyHandler(SwapCharacters, "SwapCharacters") },
- { Keys.CtrlU, MakeKeyHandler(BackwardKillLine, "BackwardKillLine") },
+ { Keys.CtrlU, MakeKeyHandler(BackwardKillInput, "BackwardKillInput") },
{ Keys.CtrlX, MakeKeyHandler(Chord, "ChordFirstKey") },
{ Keys.CtrlW, MakeKeyHandler(UnixWordRubout, "UnixWordRubout") },
{ Keys.CtrlY, MakeKeyHandler(Yank, "Yank") },
@@ -369,7 +369,7 @@ void SetDefaultEmacsBindings()
// Ctrl+X, table
[Keys.CtrlX] = new Dictionary
{
- { Keys.Backspace, MakeKeyHandler(BackwardKillLine, "BackwardKillLine") },
+ { Keys.Backspace, MakeKeyHandler(BackwardKillInput, "BackwardKillInput") },
{ Keys.CtrlE, MakeKeyHandler(ViEditVisually, "ViEditVisually") },
{ Keys.CtrlU, MakeKeyHandler(Undo, "Undo") },
{ Keys.CtrlX, MakeKeyHandler(ExchangePointAndMark, "ExchangePointAndMark") },
@@ -388,9 +388,11 @@ public static KeyHandlerGroup GetDisplayGrouping(string function)
case nameof(AcceptAndGetNext):
case nameof(AcceptLine):
case nameof(AddLine):
+ case nameof(BackwardDeleteInput):
case nameof(BackwardDeleteChar):
case nameof(BackwardDeleteLine):
case nameof(BackwardDeleteWord):
+ case nameof(BackwardKillInput):
case nameof(BackwardKillLine):
case nameof(BackwardKillWord):
case nameof(CancelLine):
@@ -408,6 +410,7 @@ public static KeyHandlerGroup GetDisplayGrouping(string function)
case nameof(DeletePreviousLines):
case nameof(DeleteToEnd):
case nameof(DeleteWord):
+ case nameof(ForwardDeleteInput):
case nameof(ForwardDeleteLine):
case nameof(InsertLineAbove):
case nameof(InsertLineBelow):
diff --git a/PSReadLine/KeyBindings.vi.cs b/PSReadLine/KeyBindings.vi.cs
index e7772955..8f4beb07 100644
--- a/PSReadLine/KeyBindings.vi.cs
+++ b/PSReadLine/KeyBindings.vi.cs
@@ -72,7 +72,7 @@ private void SetDefaultViBindings()
{ Keys.CtrlSpace, MakeKeyHandler(PossibleCompletions, "PossibleCompletions") },
{ Keys.Tab, MakeKeyHandler(ViTabCompleteNext, "ViTabCompleteNext") },
{ Keys.ShiftTab, MakeKeyHandler(ViTabCompletePrevious, "ViTabCompletePrevious") },
- { Keys.CtrlU, MakeKeyHandler(BackwardDeleteLine, "BackwardDeleteLine") },
+ { Keys.CtrlU, MakeKeyHandler(BackwardDeleteInput, "BackwardDeleteInput") },
{ Keys.CtrlV, MakeKeyHandler(Paste, "Paste") },
{ Keys.CtrlC, MakeKeyHandler(CancelLine, "CancelLine") },
{ Keys.CtrlL, MakeKeyHandler(ClearScreen, "ClearScreen") },
@@ -80,8 +80,8 @@ private void SetDefaultViBindings()
{ Keys.CtrlY, MakeKeyHandler(Redo, "Redo") },
{ Keys.CtrlZ, MakeKeyHandler(Undo, "Undo") },
{ Keys.CtrlBackspace, MakeKeyHandler(BackwardKillWord, "BackwardKillWord") },
- { Keys.CtrlEnd, MakeKeyHandler(ForwardDeleteLine, "ForwardDeleteLine") },
- { Keys.CtrlHome, MakeKeyHandler(BackwardDeleteLine, "BackwardDeleteLine") },
+ { Keys.CtrlEnd, MakeKeyHandler(ForwardDeleteInput, "ForwardDeleteInput") },
+ { Keys.CtrlHome, MakeKeyHandler(BackwardDeleteInput, "BackwardDeleteInput") },
{ Keys.CtrlRBracket, MakeKeyHandler(GotoBrace, "GotoBrace") },
{ Keys.F3, MakeKeyHandler(CharacterSearch, "CharacterSearch") },
{ Keys.ShiftF3, MakeKeyHandler(CharacterSearchBackward,"CharacterSearchBackward") },
@@ -120,13 +120,13 @@ private void SetDefaultViBindings()
{ Keys.CtrlC, MakeKeyHandler(CancelLine, "CancelLine") },
{ Keys.CtrlL, MakeKeyHandler(ClearScreen, "ClearScreen") },
{ Keys.CtrlT, MakeKeyHandler(SwapCharacters, "SwapCharacters") },
- { Keys.CtrlU, MakeKeyHandler(BackwardDeleteLine, "BackwardDeleteLine") },
+ { Keys.CtrlU, MakeKeyHandler(BackwardDeleteInput, "BackwardDeleteInput") },
{ Keys.CtrlW, MakeKeyHandler(BackwardDeleteWord, "BackwardDeleteWord") },
{ Keys.CtrlY, MakeKeyHandler(Redo, "Redo") },
{ Keys.CtrlZ, MakeKeyHandler(Undo, "Undo") },
{ Keys.CtrlBackspace, MakeKeyHandler(BackwardKillWord, "BackwardKillWord") },
- { Keys.CtrlEnd, MakeKeyHandler(ForwardDeleteLine, "ForwardDeleteLine") },
- { Keys.CtrlHome, MakeKeyHandler(BackwardDeleteLine, "BackwardDeleteLine") },
+ { Keys.CtrlEnd, MakeKeyHandler(ForwardDeleteInput, "ForwardDeleteInput") },
+ { Keys.CtrlHome, MakeKeyHandler(BackwardDeleteInput, "BackwardDeleteInput") },
{ Keys.CtrlRBracket, MakeKeyHandler(GotoBrace, "GotoBrace") },
{ Keys.F3, MakeKeyHandler(CharacterSearch, "CharacterSearch") },
{ Keys.ShiftF3, MakeKeyHandler(CharacterSearchBackward, "CharacterSearchBackward") },
diff --git a/PSReadLine/KillYank.cs b/PSReadLine/KillYank.cs
index aa20e178..179bb360 100644
--- a/PSReadLine/KillYank.cs
+++ b/PSReadLine/KillYank.cs
@@ -117,11 +117,21 @@ public static void KillLine(ConsoleKeyInfo? key = null, object arg = null)
/// Clear the input from the start of the input to the cursor. The cleared text is placed
/// in the kill ring.
///
- public static void BackwardKillLine(ConsoleKeyInfo? key = null, object arg = null)
+ public static void BackwardKillInput(ConsoleKeyInfo? key = null, object arg = null)
{
_singleton.Kill(0, _singleton._current, true);
}
+ ///
+ /// Clear the input from the start of the current logical line to the cursor. The cleared text is placed
+ /// in the kill ring.
+ ///
+ public static void BackwardKillLine(ConsoleKeyInfo? key = null, object arg = null)
+ {
+ var start = GetBeginningOfLinePos(_singleton._current);
+ _singleton.Kill(start, _singleton._current, true);
+ }
+
///
/// Clear the input from the cursor to the end of the current word. If the cursor
/// is between words, the input is cleared from the cursor to the end of the next word.
diff --git a/PSReadLine/PSReadLineResources.Designer.cs b/PSReadLine/PSReadLineResources.Designer.cs
index d26a5e4b..ac7ce268 100644
--- a/PSReadLine/PSReadLineResources.Designer.cs
+++ b/PSReadLine/PSReadLineResources.Designer.cs
@@ -115,7 +115,16 @@ internal static string BackwardDeleteCharDescription {
}
///
- /// Looks up a localized string similar to Delete text from the cursor to the start of the line.
+ /// Looks up a localized string similar to Delete text from the cursor to the start of the input.
+ ///
+ internal static string BackwardDeleteInputDescription {
+ get {
+ return ResourceManager.GetString("BackwardDeleteInputDescription", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Delete text from the cursor to the start of the current logical line.
///
internal static string BackwardDeleteLineDescription {
get {
@@ -135,6 +144,15 @@ internal static string BackwardDeleteWordDescription {
///
/// Looks up a localized string similar to Move the text from the cursor to the beginning of the line to the kill ring.
///
+ internal static string BackwardKillInputDescription {
+ get {
+ return ResourceManager.GetString("BackwardKillInputDescription", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Move the text from the start of the current logical line to the cursor to the kill ring.
+ ///
internal static string BackwardKillLineDescription {
get {
return ResourceManager.GetString("BackwardKillLineDescription", resourceCulture);
@@ -504,6 +522,15 @@ internal static string ForwardCharDescription {
///
/// Looks up a localized string similar to Delete text from the cursor to the end of the line.
///
+ internal static string ForwardDeleteInputDescription {
+ get {
+ return ResourceManager.GetString("ForwardDeleteInputDescription", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Delete text from the cursor to the end of the current logical line.
+ ///
internal static string ForwardDeleteLineDescription {
get {
return ResourceManager.GetString("ForwardDeleteLineDescription", resourceCulture);
diff --git a/PSReadLine/PSReadLineResources.resx b/PSReadLine/PSReadLineResources.resx
index 76f70996..fbc6ae0b 100644
--- a/PSReadLine/PSReadLineResources.resx
+++ b/PSReadLine/PSReadLineResources.resx
@@ -129,11 +129,17 @@
Delete the character before the cursor
+
+ Delete text from the cursor to the start of the input
+
- Delete text from the cursor to the start of the line
+ Delete text from the cursor to the start of the current logical line
+
+
+ Move the text from the cursor to the beginning of the input to the kill ring
- Move the text from the cursor to the beginning of the line to the kill ring
+ Move the text from the start of the current logical line to the cursor to the kill ring
Move to the first item in the history
@@ -180,8 +186,11 @@
Move the cursor forward one character
+
+ Delete text from the cursor to the end of the input
+
- Delete text from the cursor to the end of the line
+ Delete text from the cursor to the end of the current logical line
Move the cursor to the beginning of the next token or end of line
diff --git a/test/BasicEditingTest.VI.cs b/test/BasicEditingTest.VI.cs
index 42b66b74..c725ee49 100644
--- a/test/BasicEditingTest.VI.cs
+++ b/test/BasicEditingTest.VI.cs
@@ -570,6 +570,26 @@ public void ViDeleteToEnd()
));
}
+ [SkippableFact]
+ public void ViBackwardDeleteLine()
+ {
+ TestSetup(KeyMode.Vi);
+
+ int continuationPrefixLength = PSConsoleReadLineOptions.DefaultContinuationPrompt.Length;
+
+ Test("\"\nsome words\n\"", Keys(
+
+ _.DQuote, _.Enter,
+ " this is a line with some words", _.Enter,
+ _.DQuote, _.Escape,
+ "k6W",
+ CheckThat(() => AssertCursorLeftIs(continuationPrefixLength + 23)),
+ // delete from first non blank of line
+ "d0",
+ CheckThat(() => AssertCursorLeftIs(continuationPrefixLength))
+ ));
+ }
+
[SkippableFact]
public void ViDeleteLineToFirstChar()
{
diff --git a/test/BasicEditingTest.cs b/test/BasicEditingTest.cs
index de9fd7f2..6710181c 100644
--- a/test/BasicEditingTest.cs
+++ b/test/BasicEditingTest.cs
@@ -73,7 +73,7 @@ public void CancelLine()
}
[SkippableFact]
- public void ForwardDeleteLine()
+ public void ForwardDeleteInput()
{
ConsoleKeyInfo deleteToEnd;
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
@@ -98,7 +98,22 @@ public void ForwardDeleteLine()
}
[SkippableFact]
- public void BackwardDeleteLine()
+ public void ForwardDeleteLine()
+ {
+ TestSetup(KeyMode.Emacs);
+
+ PSConsoleReadLine.SetKeyHandler(new[] { "Shift+Tab" }, PSConsoleReadLine.ForwardDeleteLine, "", "");
+
+ Test("\"H\nWorld\"", Keys(
+ _.DQuote, "Hello", _.Enter,
+ "World", _.DQuote,
+ _.Home, _.Home, _.RightArrow, _.RightArrow,
+ _.Shift_Tab // delete to the end of the current logical line
+ ));
+ }
+
+ [SkippableFact]
+ public void BackwardDeleteInput()
{
TestSetup(KeyMode.Cmd);
diff --git a/test/KillYankTest.cs b/test/KillYankTest.cs
index 72677d51..1612e7ce 100644
--- a/test/KillYankTest.cs
+++ b/test/KillYankTest.cs
@@ -116,6 +116,16 @@ public void BackwardKillLine()
{
TestSetup(KeyMode.Emacs);
+ PSConsoleReadLine.SetKeyHandler(new[] { "Shift+Tab" }, PSConsoleReadLine.BackwardKillLine, "", "");
+
+ Test("", Keys("dir", _.Shift_Tab));
+ }
+
+ [SkippableFact]
+ public void BackwardKillInput()
+ {
+ TestSetup(KeyMode.Emacs);
+
// Kill whole line
// Check killed text by yanking
Test("ls", Keys("dir", _.Ctrl_u, "ls"));