shift-delete to delete current history search match

Popular operating systems support shift-delete to delete the selected item
in an autocompletion widgets.  We already support this in the history pager.
Let's do the same for up-arrow history search.

Related discussion: https://github.com/fish-shell/fish-shell/pull/9515
This commit is contained in:
Johannes Altmanninger 2024-04-13 20:08:12 +02:00
parent 00432df420
commit 29b309dd5f
6 changed files with 41 additions and 6 deletions

View file

@ -23,7 +23,7 @@ Notable backwards-incompatible changes
- Fish now decodes keyboard input into human-readable key names.
To make this for for a wide range of terminals, fish asks terminals to speak several keyboard protocols,
including CSI u, XTerm's ``modifyOtherKeys`` and some progressive enhancements from the `kitty keyboard protocol <https://sw.kovidgoyal.net/kitty/keyboard-protocol/>`.
including CSI u, XTerm's ``modifyOtherKeys`` and some progressive enhancements from the `kitty keyboard protocol <https://sw.kovidgoyal.net/kitty/keyboard-protocol/>`_.
Depending on terminal support, this allows to bind a lot more key combinations,
including arbitrary combinations of modifiers ``ctrl``, ``alt`` and ``shift``.
@ -112,6 +112,7 @@ New or improved bindings
- Special input functions run from bindings via ``commandline -f`` are now applied immediately instead of after the currently executing binding.
For example, ``commandline -f yank -f yank-pop`` inserts the last-but-one entry from the kill ring.
- When the cursor is on a command that resolves to an executable script, :kbd:`Alt-O` will now open that script in your editor (:issue:`10266`).
- During up-arrow history search, :kbd:`shift-delete` will delete the current search item and move to the next older item. Previously this was only supported in the history pager.
- Two improvements to the :kbd:`Alt-E` binding which edits the commandline in an external editor:
- The editor's cursor position is copied back to fish. This is currently supported for Vim and Kakoune.
- Cursor position synchronization is only supported for a set of known editors. This has been extended by also resolving aliases. For example use ``complete --wraps my-vim vim`` to synchronize cursors when `EDITOR=my-vim`.

View file

@ -229,7 +229,7 @@ The following special input functions are available:
invoke the searchable pager on history (incremental search); or if the history pager is already active, search further backwards in time.
``history-pager-delete``
permanently delete the history item selected in the history pager
permanently delete the current history item, either from the history pager or from an active up-arrow history search
``history-search-backward``
search the history for the previous match

View file

@ -1843,6 +1843,12 @@ impl HistorySearch {
&self.orig_term
}
pub fn prepare_to_search_after_deletion(&mut self) {
assert!(self.current_index != 0);
self.current_index -= 1;
self.current_item = None;
}
/// Finds the next search result. Returns `true` if one was found.
pub fn go_to_next_match(&mut self, direction: SearchDirection) -> bool {
let invalid_index = match direction {

View file

@ -2562,6 +2562,16 @@ impl ReaderData {
self.insert_string(EditableLineTag::SearchField, &search_string);
}
rl::HistoryPagerDelete => {
// Also applies to ordinary history search.
if !self.history_search.is_at_end() {
self.history
.remove(self.history_search.current_result().to_owned());
self.history.save();
self.history_search.handle_deletion();
self.update_command_line_from_history_search();
self.inputter.function_set_status(true);
return;
}
if !self.history_pager_active {
self.inputter.function_set_status(false);
return;
@ -4674,6 +4684,7 @@ fn command_ends_history_search(c: ReadlineCmd) -> bool {
| rl::HistorySearchForward
| rl::HistoryTokenSearchBackward
| rl::HistoryTokenSearchForward
| rl::HistoryPagerDelete
| rl::BeginningOfHistory
| rl::EndOfHistory
| rl::Repaint

View file

@ -133,6 +133,14 @@ impl ReaderHistorySearch {
self.skips.insert(s)
}
pub fn handle_deletion(&mut self) {
assert!(!self.is_at_end());
self.matches.remove(self.match_index);
self.match_index -= 1;
self.search_mut().prepare_to_search_after_deletion();
self.move_backwards();
}
/// Reset, beginning a new line or token mode search.
pub fn reset_to_mode(
&mut self,

View file

@ -46,11 +46,20 @@ isolated-tmux send-keys Enter
isolated-tmux capture-pane -p | grep 'prompt 2>'
isolated-tmux send-keys C-c
isolated-tmux send-keys 'echo 1' Enter 'echo 2' Enter 'echo 3' Enter
isolated-tmux send-keys C-l echo Up
isolated-tmux send-keys echo M-d
tmux-sleep
isolated-tmux capture-pane -p
#CHECK: prompt 5> echo 2
isolated-tmux send-keys C-c
tmux-sleep
isolated-tmux send-keys "echo sdifjsdoifjsdoifj" Enter
tmux-sleep
isolated-tmux capture-pane -p | grep "^sdifjsdoifjsdoifj\|prompt 3>"
isolated-tmux capture-pane -p | grep "^sdifjsdoifjsdoifj\|prompt 6>"
# CHECK: sdifjsdoifjsdoifj
# CHECK: prompt 3>
# CHECK: prompt 6>
isolated-tmux send-keys C-e C-u C-r
tmux-sleep
isolated-tmux send-keys "echo sdifjsdoifjsdoifj"
@ -61,6 +70,6 @@ isolated-tmux capture-pane -p | grep "(no matches)"
# CHECK: (no matches)
isolated-tmux send-keys Enter C-e C-u "echo foo" Enter
tmux-sleep
isolated-tmux capture-pane -p | grep "^foo\|prompt 4>"
isolated-tmux capture-pane -p | grep "^foo\|prompt 7>"
# CHECK: foo
# CHECK: prompt 4>
# CHECK: prompt 7>