From 73077262c33af1a907497c0ecd6865f3b438d607 Mon Sep 17 00:00:00 2001 From: Ralf Rastlos Date: Wed, 5 Jul 2023 03:10:25 +0200 Subject: [PATCH 1/3] added camel humps navigation --- PSReadLine/Humps.cs | 119 ++++++++++ PSReadLine/KeyBindings.cs | 484 +++++++++++++++++++------------------- PSReadLine/Movement.cs | 61 +++++ 3 files changed, 423 insertions(+), 241 deletions(-) create mode 100644 PSReadLine/Humps.cs diff --git a/PSReadLine/Humps.cs b/PSReadLine/Humps.cs new file mode 100644 index 000000000..455cf519f --- /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 89564228d..34e235928 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,230 @@ 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(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(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; } } diff --git a/PSReadLine/Movement.cs b/PSReadLine/Movement.cs index da52230e6..9a32d4061 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. From b83add6d944f35f30977552ca06eb03de4a4745f Mon Sep 17 00:00:00 2001 From: Ralf Rastlos Date: Wed, 5 Jul 2023 03:24:57 +0200 Subject: [PATCH 2/3] added camel humps selection --- PSReadLine/KeyBindings.cs | 2 ++ PSReadLine/KillYank.cs | 16 ++++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/PSReadLine/KeyBindings.cs b/PSReadLine/KeyBindings.cs index 34e235928..be09e3bbd 100644 --- a/PSReadLine/KeyBindings.cs +++ b/PSReadLine/KeyBindings.cs @@ -615,8 +615,10 @@ public static KeyHandlerGroup GetDisplayGrouping(string function) 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): diff --git a/PSReadLine/KillYank.cs b/PSReadLine/KillYank.cs index f05fc8ba0..bcc8731fc 100644 --- a/PSReadLine/KillYank.cs +++ b/PSReadLine/KillYank.cs @@ -383,6 +383,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 +407,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. /// From 97225cd0470b6bed735dd49caadd370fc210c26c Mon Sep 17 00:00:00 2001 From: Ralf Rastlos Date: Wed, 5 Jul 2023 03:34:10 +0200 Subject: [PATCH 3/3] added camel humps backward deletion --- PSReadLine/KeyBindings.cs | 1 + PSReadLine/KillYank.cs | 11 +++++++++++ 2 files changed, 12 insertions(+) diff --git a/PSReadLine/KeyBindings.cs b/PSReadLine/KeyBindings.cs index be09e3bbd..5693d1b75 100644 --- a/PSReadLine/KeyBindings.cs +++ b/PSReadLine/KeyBindings.cs @@ -414,6 +414,7 @@ public static KeyHandlerGroup GetDisplayGrouping(string function) case nameof(BackwardKillInput): case nameof(BackwardKillLine): case nameof(BackwardKillWord): + case nameof(BackwardKillHump): case nameof(CancelLine): case nameof(CapitalizeWord): case nameof(Copy): diff --git a/PSReadLine/KillYank.cs b/PSReadLine/KillYank.cs index bcc8731fc..49ee5d3e8 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