diff --git a/PSReadLine/Humps.cs b/PSReadLine/Humps.cs
new file mode 100644
index 00000000..455cf519
--- /dev/null
+++ b/PSReadLine/Humps.cs
@@ -0,0 +1,119 @@
+/********************************************************************++
+Copyright (c) Darkstar Developments GmbH 2023. All rights reserved.
+--********************************************************************/
+
+using System.Collections.Generic;
+using System.Management.Automation.Language;
+
+namespace Microsoft.PowerShell
+{
+ public partial class PSConsoleReadLine
+ {
+ private enum FindHumpMode
+ {
+ CurrentOrNext,
+ Next,
+ Previous,
+ }
+
+ ///
+ /// Find the end of the current/next camel hump.
+ ///
+ public int FindForwardHumpPoint(string wordDelimiters)
+ {
+ int i = _current;
+ if (i == _buffer.Length)
+ return i;
+
+ if (!InWord(i, wordDelimiters))
+ {
+ // Scan to end of current non-word region
+ while (i < _buffer.Length)
+ {
+ if (InWord(i, wordDelimiters))
+ break;
+
+ i += 1;
+ }
+ }
+ else
+ {
+ if (AtStartOfHump(i, wordDelimiters))
+ i += 1;
+
+ // scan to the end of this hump
+ while (i < _buffer.Length)
+ {
+ if (!InHump(i, wordDelimiters))
+ break;
+
+ i += 1;
+ }
+ }
+
+ return i;
+ }
+
+
+ ///
+ /// Find the beginning of this camel hump.
+ ///
+ public int FindBackwardHumpPoint(string wordDelimiters)
+ {
+ int i = _current - 1;
+ if (i < 0)
+ return 0;
+
+ if (!InWord(i, wordDelimiters))
+ {
+ // scan backwards until we are at the end of the previous word.
+ while (i > 0)
+ {
+ if (InWord(i, wordDelimiters))
+ {
+ // set back one step because we want to be behind the last letter of the word / hump
+ i += 1;
+ break;
+ }
+
+ i -= 1;
+ }
+ }
+ else
+ {
+ // scan backwards until we are at the end of the previous word.
+ while (i > 0)
+ {
+ if (!InHump(i, wordDelimiters))
+ break;
+
+ i -= 1;
+ }
+ }
+
+ return i;
+ }
+
+ private bool AtStartOfHump(int index, string wordDelimiters)
+ {
+ char c = _buffer[index];
+ return AtStartOfHump(c, wordDelimiters);
+ }
+
+ private bool AtStartOfHump(char c, string wordDelimiters)
+ {
+ return !char.IsWhiteSpace(c) && wordDelimiters.IndexOf(c) < 0 && char.IsUpper(c);
+ }
+
+ private bool InHump(int index, string wordDelimiters)
+ {
+ char c = _buffer[index];
+ return InHump(c, wordDelimiters);
+ }
+
+ private bool InHump(char c, string wordDelimiters)
+ {
+ return !char.IsWhiteSpace(c) && wordDelimiters.IndexOf(c) < 0 && char.IsLower(c);
+ }
+ }
+}
\ No newline at end of file
diff --git a/PSReadLine/KeyBindings.cs b/PSReadLine/KeyBindings.cs
index 89564228..5693d1b7 100644
--- a/PSReadLine/KeyBindings.cs
+++ b/PSReadLine/KeyBindings.cs
@@ -83,25 +83,25 @@ public static string GetGroupingDescription(KeyHandlerGroup grouping)
{
switch (grouping)
{
- case KeyHandlerGroup.Basic:
- return PSReadLineResources.BasicGrouping;
- case KeyHandlerGroup.CursorMovement:
- return PSReadLineResources.CursorMovementGrouping;
- case KeyHandlerGroup.History:
- return PSReadLineResources.HistoryGrouping;
- case KeyHandlerGroup.Completion:
- return PSReadLineResources.CompletionGrouping;
- case KeyHandlerGroup.Prediction:
- return PSReadLineResources.PredictionGrouping;
- case KeyHandlerGroup.Miscellaneous:
- return PSReadLineResources.MiscellaneousGrouping;
- case KeyHandlerGroup.Selection:
- return PSReadLineResources.SelectionGrouping;
- case KeyHandlerGroup.Search:
- return PSReadLineResources.SearchGrouping;
- case KeyHandlerGroup.Custom:
- return PSReadLineResources.CustomGrouping;
- default: return "";
+ case KeyHandlerGroup.Basic:
+ return PSReadLineResources.BasicGrouping;
+ case KeyHandlerGroup.CursorMovement:
+ return PSReadLineResources.CursorMovementGrouping;
+ case KeyHandlerGroup.History:
+ return PSReadLineResources.HistoryGrouping;
+ case KeyHandlerGroup.Completion:
+ return PSReadLineResources.CompletionGrouping;
+ case KeyHandlerGroup.Prediction:
+ return PSReadLineResources.PredictionGrouping;
+ case KeyHandlerGroup.Miscellaneous:
+ return PSReadLineResources.MiscellaneousGrouping;
+ case KeyHandlerGroup.Selection:
+ return PSReadLineResources.SelectionGrouping;
+ case KeyHandlerGroup.Search:
+ return PSReadLineResources.SearchGrouping;
+ case KeyHandlerGroup.Custom:
+ return PSReadLineResources.CustomGrouping;
+ default: return "";
}
}
@@ -403,228 +403,233 @@ public static KeyHandlerGroup GetDisplayGrouping(string function)
{
switch (function)
{
- case nameof(Abort):
- case nameof(AcceptAndGetNext):
- case nameof(AcceptLine):
- case nameof(AddLine):
- case nameof(BackwardDeleteChar):
- case nameof(BackwardDeleteInput):
- case nameof(BackwardDeleteLine):
- case nameof(BackwardDeleteWord):
- case nameof(BackwardKillInput):
- case nameof(BackwardKillLine):
- case nameof(BackwardKillWord):
- case nameof(CancelLine):
- case nameof(CapitalizeWord):
- case nameof(Copy):
- case nameof(CopyOrCancelLine):
- case nameof(Cut):
- case nameof(DeleteChar):
- case nameof(DeleteCharOrExit):
- case nameof(DeleteEndOfBuffer):
- case nameof(DeleteEndOfWord):
- case nameof(DeleteLine):
- case nameof(DeleteLineToFirstChar):
- case nameof(DeleteNextLines):
- case nameof(DeletePreviousLines):
- case nameof(DeleteRelativeLines):
- case nameof(DeleteToEnd):
- case nameof(DeleteWord):
- case nameof(DowncaseWord):
- case nameof(ForwardDeleteInput):
- case nameof(ForwardDeleteLine):
- case nameof(InsertLineAbove):
- case nameof(InsertLineBelow):
- case nameof(InvertCase):
- case nameof(KillLine):
- case nameof(KillRegion):
- case nameof(KillWord):
- case nameof(Paste):
- case nameof(PasteAfter):
- case nameof(PasteBefore):
- case nameof(PrependAndAccept):
- case nameof(Redo):
- case nameof(RepeatLastCommand):
- case nameof(RevertLine):
- case nameof(ShellBackwardKillWord):
- case nameof(ShellKillWord):
- case nameof(SwapCharacters):
- case nameof(Undo):
- case nameof(UndoAll):
- case nameof(UnixWordRubout):
- case nameof(UpcaseWord):
- case nameof(ValidateAndAcceptLine):
- case nameof(ViAcceptLine):
- case nameof(ViAcceptLineOrExit):
- case nameof(ViAppendLine):
- case nameof(ViBackwardDeleteGlob):
- case nameof(ViBackwardGlob):
- case nameof(ViDeleteBrace):
- case nameof(ViDeleteEndOfGlob):
- case nameof(ViDeleteGlob):
- case nameof(ViDeleteToBeforeChar):
- case nameof(ViDeleteToBeforeCharBackward):
- case nameof(ViDeleteToChar):
- case nameof(ViDeleteToCharBackward):
- case nameof(ViInsertAtBegining):
- case nameof(ViInsertAtEnd):
- case nameof(ViInsertLine):
- case nameof(ViInsertWithAppend):
- case nameof(ViInsertWithDelete):
- case nameof(ViJoinLines):
- case nameof(ViReplaceToBeforeChar):
- case nameof(ViReplaceToBeforeCharBackward):
- case nameof(ViReplaceToChar):
- case nameof(ViReplaceToCharBackward):
- case nameof(ViYankBeginningOfLine):
- case nameof(ViYankEndOfGlob):
- case nameof(ViYankEndOfWord):
- case nameof(ViYankLeft):
- case nameof(ViYankLine):
- case nameof(ViYankNextGlob):
- case nameof(ViYankNextWord):
- case nameof(ViYankPercent):
- case nameof(ViYankPreviousGlob):
- case nameof(ViYankPreviousWord):
- case nameof(ViYankRight):
- case nameof(ViYankToEndOfLine):
- case nameof(ViYankToFirstChar):
- case nameof(Yank):
- case nameof(YankLastArg):
- case nameof(YankNthArg):
- case nameof(YankPop):
- return KeyHandlerGroup.Basic;
-
- // The following are private so cannot be used with a custom binding.
- case nameof(BackwardReplaceChar):
- case nameof(ReplaceChar):
- case nameof(ReplaceCharInPlace):
- case nameof(ViBackwardReplaceGlob):
- case nameof(ViBackwardReplaceLine):
- case nameof(ViBackwardReplaceLineToFirstChar):
- case nameof(ViBackwardReplaceWord):
- case nameof(ViReplaceBrace):
- case nameof(ViReplaceEndOfGlob):
- case nameof(ViReplaceEndOfWord):
- case nameof(ViReplaceGlob):
- case nameof(ViReplaceLine):
- case nameof(ViReplaceToEnd):
- case nameof(ViReplaceUntilEsc):
- case nameof(ViReplaceWord):
- return KeyHandlerGroup.Basic;
-
- case nameof(BackwardChar):
- case nameof(BackwardWord):
- case nameof(BeginningOfLine):
- case nameof(EndOfLine):
- case nameof(ForwardChar):
- case nameof(ForwardWord):
- case nameof(GotoBrace):
- case nameof(GotoColumn):
- case nameof(GotoFirstNonBlankOfLine):
- case nameof(MoveToEndOfLine):
- case nameof(MoveToFirstLine):
- case nameof(MoveToLastLine):
- case nameof(NextLine):
- case nameof(NextWord):
- case nameof(NextWordEnd):
- case nameof(PreviousLine):
- case nameof(ShellBackwardWord):
- case nameof(ShellForwardWord):
- case nameof(ShellNextWord):
- case nameof(ViBackwardChar):
- case nameof(ViBackwardWord):
- case nameof(ViForwardChar):
- case nameof(ViEndOfGlob):
- case nameof(ViEndOfPreviousGlob):
- case nameof(ViGotoBrace):
- case nameof(ViNextGlob):
- case nameof(ViNextWord):
- return KeyHandlerGroup.CursorMovement;
-
- case nameof(BeginningOfHistory):
- case nameof(ClearHistory):
- case nameof(EndOfHistory):
- case nameof(ForwardSearchHistory):
- case nameof(HistorySearchBackward):
- case nameof(HistorySearchForward):
- case nameof(NextHistory):
- case nameof(PreviousHistory):
- case nameof(ReverseSearchHistory):
- case nameof(ViSearchHistoryBackward):
- return KeyHandlerGroup.History;
-
- case nameof(Complete):
- case nameof(MenuComplete):
- case nameof(PossibleCompletions):
- case nameof(TabCompleteNext):
- case nameof(TabCompletePrevious):
- case nameof(ViTabCompleteNext):
- case nameof(ViTabCompletePrevious):
- return KeyHandlerGroup.Completion;
-
- case nameof(AcceptSuggestion):
- case nameof(AcceptNextSuggestionWord):
- case nameof(NextSuggestion):
- case nameof(PreviousSuggestion):
- case nameof(SwitchPredictionView):
- case nameof(ShowFullPredictionTooltip):
- return KeyHandlerGroup.Prediction;
-
- case nameof(CaptureScreen):
- case nameof(ClearScreen):
- case nameof(DigitArgument):
- case nameof(InvokePrompt):
- case nameof(ScrollDisplayDown):
- case nameof(ScrollDisplayDownLine):
- case nameof(ScrollDisplayToCursor):
- case nameof(ScrollDisplayTop):
- case nameof(ScrollDisplayUp):
- case nameof(ScrollDisplayUpLine):
- case nameof(SelfInsert):
- case nameof(ShowKeyBindings):
- case nameof(ViCommandMode):
- case nameof(ViDigitArgumentInChord):
- case nameof(ViEditVisually):
- case nameof(ViExit):
- case nameof(ViInsertMode):
- case nameof(ViDGChord):
- case nameof(WhatIsKey):
- case nameof(ShowCommandHelp):
- case nameof(ShowParameterHelp):
- return KeyHandlerGroup.Miscellaneous;
-
- case nameof(CharacterSearch):
- case nameof(CharacterSearchBackward):
- case nameof(RepeatLastCharSearch):
- case nameof(RepeatLastCharSearchBackwards):
- case nameof(RepeatSearch):
- case nameof(RepeatSearchBackward):
- case nameof(SearchChar):
- case nameof(SearchCharBackward):
- case nameof(SearchCharBackwardWithBackoff):
- case nameof(SearchCharWithBackoff):
- case nameof(SearchForward):
- return KeyHandlerGroup.Search;
-
- case nameof(ExchangePointAndMark):
- case nameof(SetMark):
- case nameof(SelectAll):
- case nameof(SelectBackwardChar):
- case nameof(SelectBackwardsLine):
- case nameof(SelectBackwardWord):
- case nameof(SelectForwardChar):
- case nameof(SelectForwardWord):
- case nameof(SelectLine):
- case nameof(SelectNextWord):
- case nameof(SelectShellBackwardWord):
- case nameof(SelectShellForwardWord):
- case nameof(SelectShellNextWord):
- case nameof(SelectCommandArgument):
- return KeyHandlerGroup.Selection;
-
- default:
- return KeyHandlerGroup.Custom;
+ case nameof(Abort):
+ case nameof(AcceptAndGetNext):
+ case nameof(AcceptLine):
+ case nameof(AddLine):
+ case nameof(BackwardDeleteChar):
+ case nameof(BackwardDeleteInput):
+ case nameof(BackwardDeleteLine):
+ case nameof(BackwardDeleteWord):
+ case nameof(BackwardKillInput):
+ case nameof(BackwardKillLine):
+ case nameof(BackwardKillWord):
+ case nameof(BackwardKillHump):
+ case nameof(CancelLine):
+ case nameof(CapitalizeWord):
+ case nameof(Copy):
+ case nameof(CopyOrCancelLine):
+ case nameof(Cut):
+ case nameof(DeleteChar):
+ case nameof(DeleteCharOrExit):
+ case nameof(DeleteEndOfBuffer):
+ case nameof(DeleteEndOfWord):
+ case nameof(DeleteLine):
+ case nameof(DeleteLineToFirstChar):
+ case nameof(DeleteNextLines):
+ case nameof(DeletePreviousLines):
+ case nameof(DeleteRelativeLines):
+ case nameof(DeleteToEnd):
+ case nameof(DeleteWord):
+ case nameof(DowncaseWord):
+ case nameof(ForwardDeleteInput):
+ case nameof(ForwardDeleteLine):
+ case nameof(InsertLineAbove):
+ case nameof(InsertLineBelow):
+ case nameof(InvertCase):
+ case nameof(KillLine):
+ case nameof(KillRegion):
+ case nameof(KillWord):
+ case nameof(Paste):
+ case nameof(PasteAfter):
+ case nameof(PasteBefore):
+ case nameof(PrependAndAccept):
+ case nameof(Redo):
+ case nameof(RepeatLastCommand):
+ case nameof(RevertLine):
+ case nameof(ShellBackwardKillWord):
+ case nameof(ShellKillWord):
+ case nameof(SwapCharacters):
+ case nameof(Undo):
+ case nameof(UndoAll):
+ case nameof(UnixWordRubout):
+ case nameof(UpcaseWord):
+ case nameof(ValidateAndAcceptLine):
+ case nameof(ViAcceptLine):
+ case nameof(ViAcceptLineOrExit):
+ case nameof(ViAppendLine):
+ case nameof(ViBackwardDeleteGlob):
+ case nameof(ViBackwardGlob):
+ case nameof(ViDeleteBrace):
+ case nameof(ViDeleteEndOfGlob):
+ case nameof(ViDeleteGlob):
+ case nameof(ViDeleteToBeforeChar):
+ case nameof(ViDeleteToBeforeCharBackward):
+ case nameof(ViDeleteToChar):
+ case nameof(ViDeleteToCharBackward):
+ case nameof(ViInsertAtBegining):
+ case nameof(ViInsertAtEnd):
+ case nameof(ViInsertLine):
+ case nameof(ViInsertWithAppend):
+ case nameof(ViInsertWithDelete):
+ case nameof(ViJoinLines):
+ case nameof(ViReplaceToBeforeChar):
+ case nameof(ViReplaceToBeforeCharBackward):
+ case nameof(ViReplaceToChar):
+ case nameof(ViReplaceToCharBackward):
+ case nameof(ViYankBeginningOfLine):
+ case nameof(ViYankEndOfGlob):
+ case nameof(ViYankEndOfWord):
+ case nameof(ViYankLeft):
+ case nameof(ViYankLine):
+ case nameof(ViYankNextGlob):
+ case nameof(ViYankNextWord):
+ case nameof(ViYankPercent):
+ case nameof(ViYankPreviousGlob):
+ case nameof(ViYankPreviousWord):
+ case nameof(ViYankRight):
+ case nameof(ViYankToEndOfLine):
+ case nameof(ViYankToFirstChar):
+ case nameof(Yank):
+ case nameof(YankLastArg):
+ case nameof(YankNthArg):
+ case nameof(YankPop):
+ return KeyHandlerGroup.Basic;
+
+ // The following are private so cannot be used with a custom binding.
+ case nameof(BackwardReplaceChar):
+ case nameof(ReplaceChar):
+ case nameof(ReplaceCharInPlace):
+ case nameof(ViBackwardReplaceGlob):
+ case nameof(ViBackwardReplaceLine):
+ case nameof(ViBackwardReplaceLineToFirstChar):
+ case nameof(ViBackwardReplaceWord):
+ case nameof(ViReplaceBrace):
+ case nameof(ViReplaceEndOfGlob):
+ case nameof(ViReplaceEndOfWord):
+ case nameof(ViReplaceGlob):
+ case nameof(ViReplaceLine):
+ case nameof(ViReplaceToEnd):
+ case nameof(ViReplaceUntilEsc):
+ case nameof(ViReplaceWord):
+ return KeyHandlerGroup.Basic;
+
+ case nameof(BackwardChar):
+ case nameof(BackwardWord):
+ case nameof(BackwardHump):
+ case nameof(BeginningOfLine):
+ case nameof(EndOfLine):
+ case nameof(ForwardChar):
+ case nameof(ForwardWord):
+ case nameof(ForwardHump):
+ case nameof(GotoBrace):
+ case nameof(GotoColumn):
+ case nameof(GotoFirstNonBlankOfLine):
+ case nameof(MoveToEndOfLine):
+ case nameof(MoveToFirstLine):
+ case nameof(MoveToLastLine):
+ case nameof(NextLine):
+ case nameof(NextWord):
+ case nameof(NextWordEnd):
+ case nameof(PreviousLine):
+ case nameof(ShellBackwardWord):
+ case nameof(ShellForwardWord):
+ case nameof(ShellNextWord):
+ case nameof(ViBackwardChar):
+ case nameof(ViBackwardWord):
+ case nameof(ViForwardChar):
+ case nameof(ViEndOfGlob):
+ case nameof(ViEndOfPreviousGlob):
+ case nameof(ViGotoBrace):
+ case nameof(ViNextGlob):
+ case nameof(ViNextWord):
+ return KeyHandlerGroup.CursorMovement;
+
+ case nameof(BeginningOfHistory):
+ case nameof(ClearHistory):
+ case nameof(EndOfHistory):
+ case nameof(ForwardSearchHistory):
+ case nameof(HistorySearchBackward):
+ case nameof(HistorySearchForward):
+ case nameof(NextHistory):
+ case nameof(PreviousHistory):
+ case nameof(ReverseSearchHistory):
+ case nameof(ViSearchHistoryBackward):
+ return KeyHandlerGroup.History;
+
+ case nameof(Complete):
+ case nameof(MenuComplete):
+ case nameof(PossibleCompletions):
+ case nameof(TabCompleteNext):
+ case nameof(TabCompletePrevious):
+ case nameof(ViTabCompleteNext):
+ case nameof(ViTabCompletePrevious):
+ return KeyHandlerGroup.Completion;
+
+ case nameof(AcceptSuggestion):
+ case nameof(AcceptNextSuggestionWord):
+ case nameof(NextSuggestion):
+ case nameof(PreviousSuggestion):
+ case nameof(SwitchPredictionView):
+ case nameof(ShowFullPredictionTooltip):
+ return KeyHandlerGroup.Prediction;
+
+ case nameof(CaptureScreen):
+ case nameof(ClearScreen):
+ case nameof(DigitArgument):
+ case nameof(InvokePrompt):
+ case nameof(ScrollDisplayDown):
+ case nameof(ScrollDisplayDownLine):
+ case nameof(ScrollDisplayToCursor):
+ case nameof(ScrollDisplayTop):
+ case nameof(ScrollDisplayUp):
+ case nameof(ScrollDisplayUpLine):
+ case nameof(SelfInsert):
+ case nameof(ShowKeyBindings):
+ case nameof(ViCommandMode):
+ case nameof(ViDigitArgumentInChord):
+ case nameof(ViEditVisually):
+ case nameof(ViExit):
+ case nameof(ViInsertMode):
+ case nameof(ViDGChord):
+ case nameof(WhatIsKey):
+ case nameof(ShowCommandHelp):
+ case nameof(ShowParameterHelp):
+ return KeyHandlerGroup.Miscellaneous;
+
+ case nameof(CharacterSearch):
+ case nameof(CharacterSearchBackward):
+ case nameof(RepeatLastCharSearch):
+ case nameof(RepeatLastCharSearchBackwards):
+ case nameof(RepeatSearch):
+ case nameof(RepeatSearchBackward):
+ case nameof(SearchChar):
+ case nameof(SearchCharBackward):
+ case nameof(SearchCharBackwardWithBackoff):
+ case nameof(SearchCharWithBackoff):
+ case nameof(SearchForward):
+ return KeyHandlerGroup.Search;
+
+ case nameof(ExchangePointAndMark):
+ case nameof(SetMark):
+ case nameof(SelectAll):
+ case nameof(SelectBackwardChar):
+ case nameof(SelectBackwardsLine):
+ case nameof(SelectBackwardWord):
+ case nameof(SelectBackwardHump):
+ case nameof(SelectForwardChar):
+ case nameof(SelectForwardWord):
+ case nameof(SelectForwardHump):
+ case nameof(SelectLine):
+ case nameof(SelectNextWord):
+ case nameof(SelectShellBackwardWord):
+ case nameof(SelectShellForwardWord):
+ case nameof(SelectShellNextWord):
+ case nameof(SelectCommandArgument):
+ return KeyHandlerGroup.Selection;
+
+ default:
+ return KeyHandlerGroup.Custom;
}
}
diff --git a/PSReadLine/KillYank.cs b/PSReadLine/KillYank.cs
index f05fc8ba..49ee5d3e 100644
--- a/PSReadLine/KillYank.cs
+++ b/PSReadLine/KillYank.cs
@@ -169,6 +169,17 @@ public static void BackwardKillWord(ConsoleKeyInfo? key = null, object arg = nul
_singleton.Kill(i, _singleton._current - i, true);
}
+ ///
+ /// Clear the input from the start of the current hump to the cursor. If the cursor
+ /// is between words, the input is cleared from the start of the previous hump to the
+ /// cursor. The cleared text is placed in the kill ring.
+ ///
+ public static void BackwardKillHump(ConsoleKeyInfo? key = null, object arg = null)
+ {
+ int i = _singleton.FindBackwardHumpPoint(_singleton.Options.WordDelimiters);
+ _singleton.Kill(i, _singleton._current - i, true);
+ }
+
///
/// Clear the input from the start of the current word to the cursor. If the cursor
/// is between words, the input is cleared from the start of the previous word to the
@@ -383,6 +394,14 @@ public static void SelectBackwardWord(ConsoleKeyInfo? key = null, object arg = n
_singleton.VisualSelectionCommon(() => BackwardWord(key, arg));
}
+ ///
+ /// Adjust the current selection to include the previous hump.
+ ///
+ public static void SelectBackwardHump(ConsoleKeyInfo? key = null, object arg = null)
+ {
+ _singleton.VisualSelectionCommon(() => BackwardHump(key, arg));
+ }
+
///
/// Adjust the current selection to include the next word.
///
@@ -399,6 +418,14 @@ public static void SelectForwardWord(ConsoleKeyInfo? key = null, object arg = nu
_singleton.VisualSelectionCommon(() => ForwardWord(key, arg));
}
+ ///
+ /// Adjust the current selection to include the next hump using ForwardHump.
+ ///
+ public static void SelectForwardHump(ConsoleKeyInfo? key = null, object arg = null)
+ {
+ _singleton.VisualSelectionCommon(() => ForwardHump(key, arg));
+ }
+
///
/// Adjust the current selection to include the next word using ShellForwardWord.
///
diff --git a/PSReadLine/Movement.cs b/PSReadLine/Movement.cs
index da52230e..9a32d406 100644
--- a/PSReadLine/Movement.cs
+++ b/PSReadLine/Movement.cs
@@ -337,6 +337,36 @@ public static void ForwardWord(ConsoleKeyInfo? key = null, object arg = null)
}
}
+ ///
+ /// Move the cursor forward to the end of the current hump, or if between words,
+ /// to the end of the next word. Word boundaries are defined by a configurable
+ /// set of characters.
+ ///
+ public static void ForwardHump(ConsoleKeyInfo? key = null, object arg = null)
+ {
+ if (!TryGetArgAsInt(arg, out var numericArg, 1))
+ {
+ return;
+ }
+
+ if (_singleton._current == _singleton._buffer.Length && numericArg > 0)
+ {
+ AcceptNextSuggestionWord(numericArg);
+ return;
+ }
+
+ if (numericArg < 0)
+ {
+ BackwardHump(key, -numericArg);
+ return;
+ }
+
+ while (numericArg-- > 0)
+ {
+ _singleton.MoveCursor(_singleton.FindForwardHumpPoint(_singleton.Options.WordDelimiters));
+ }
+ }
+
///
/// Move the cursor forward to the start of the next word.
/// Word boundaries are defined by PowerShell tokens.
@@ -407,6 +437,37 @@ public static void BackwardWord(ConsoleKeyInfo? key = null, object arg = null)
}
}
+ ///
+ /// Move the cursor back to the start of the current hump, or if between words,
+ /// the start of the previous word. Word boundaries are defined by a configurable
+ /// set of characters.
+ ///
+ public static void BackwardHump(ConsoleKeyInfo? key = null, object arg = null)
+ {
+ if (!TryGetArgAsInt(arg, out var numericArg, 1))
+ {
+ return;
+ }
+
+ if (numericArg < 0)
+ {
+ if (CheckIsBound(ForwardWord))
+ {
+ ForwardHump(key, -numericArg);
+ }
+ else
+ {
+ ForwardHump(key, -numericArg);
+ }
+ return;
+ }
+
+ while (numericArg-- > 0)
+ {
+ _singleton.MoveCursor(_singleton.FindBackwardHumpPoint(_singleton.Options.WordDelimiters));
+ }
+ }
+
///
/// Move the cursor back to the start of the current word, or if between words,
/// the start of the previous word. Word boundaries are defined by PowerShell tokens.