From 5de6f4bb3d8c3d4db1fd0b66c2ebfa59682ccc84 Mon Sep 17 00:00:00 2001 From: Johannes Altmanninger Date: Mon, 23 Dec 2024 13:51:07 +0100 Subject: [PATCH] Provide old implementation of cancel-commandline as fallback __fish_cancel_commandline was unused (even before) and has some issues on multiline commandlines. Make it use the previously active logic. Closes #10935 --- CHANGELOG.rst | 2 +- .../functions/__fish_cancel_commandline.fish | 30 ++---------------- src/input.rs | 1 + src/input_common.rs | 1 + src/reader.rs | 31 ++++++++++++++++++- 5 files changed, 35 insertions(+), 30 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 18943f413..b5c39152b 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -94,7 +94,7 @@ Notable improvements and fixes This build system is experimental; the main build system, using ``cmake``, remains the recommended approach for packaging and installation to a prefix. - A new function ``fish_should_add_to_history`` can be overridden to decide whether a command should be added to the history (:issue:`10302`). -- :kbd:`ctrl-c` during command input no longer prints ``^C`` and a new prompt, but merely clears the command line. This restores the behavior from version 2.2. To revert to the old behavior, use ``bind ctrl-c __fish_cancel_commandline`` (:issue:`10213`). +- :kbd:`ctrl-c` during command input no longer prints ``^C`` and a new prompt, but merely clears the command line. This restores the behavior from version 2.2. To revert to the old behavior, use ``for mode in (bind --list-modes); bind -M $mode ctrl-c cancel-commandline-traditional; end`` (:issue:`10213`). - Bindings can now mix special input functions and shell commands, so ``bind ctrl-g expand-abbr "commandline -i \n"`` works as expected (:issue:`8186`). - Special input functions run from bindings via ``commandline -f`` are now applied immediately, instead of after the currently executing binding (:issue:`3031`). For example, ``commandline -i foo; commandline | grep foo`` succeeds now. diff --git a/share/functions/__fish_cancel_commandline.fish b/share/functions/__fish_cancel_commandline.fish index 79bc3b302..6d1a37dc2 100644 --- a/share/functions/__fish_cancel_commandline.fish +++ b/share/functions/__fish_cancel_commandline.fish @@ -1,30 +1,4 @@ -function __fish_setup_cancel_text -v fish_color_cancel -v fish_color_normal - set -g __fish_cancel_text "^C" - if set -q fish_color_cancel - set __fish_cancel_text (echo -sn (set_color $fish_color_cancel) $__fish_cancel_text (set_color normal)) - end - if command -sq tput - # Clear to EOL (to erase any autosuggestions) - set __fish_cancel_text (echo -sn $__fish_cancel_text (tput el; or tput ce)) - end -end -__fish_setup_cancel_text - -# This is meant to be bound to something like \cC. +# This is meant to be bound to something like ctrl-c function __fish_cancel_commandline - set -l cmd (commandline) - if test -n "$cmd" - echo -sn $__fish_cancel_text - # `commandline -L` prints the line the cursor is on (starting from the prompt), so move the cursor - # "to the end" then call `commandline -L` to get the total number of lines typed in at the prompt. - commandline -C 10000000 - printf (string repeat -n (commandline -L) "\n") - commandline "" - emit fish_cancel - end - - # cancel: Close the pager if it's open (#4298) - # repaint: Repaint even if we haven't cancelled anything so the prompt refreshes - # and the terminal scrolls to it. - commandline -f cancel -f repaint + commandline -f cancel-commandline-traditional end diff --git a/src/input.rs b/src/input.rs index 6407ed9b0..fdca0f863 100644 --- a/src/input.rs +++ b/src/input.rs @@ -146,6 +146,7 @@ const INPUT_FUNCTION_METADATA: &[InputFunctionMetadata] = &[ make_md(L!("beginning-of-line"), ReadlineCmd::BeginningOfLine), make_md(L!("cancel"), ReadlineCmd::Cancel), make_md(L!("cancel-commandline"), ReadlineCmd::CancelCommandline), + make_md(L!("cancel-commandline-traditional"), ReadlineCmd::CancelCommandlineTraditional), make_md(L!("capitalize-word"), ReadlineCmd::CapitalizeWord), make_md(L!("clear-screen"), ReadlineCmd::ClearScreenAndRepaint), make_md(L!("complete"), ReadlineCmd::Complete), diff --git a/src/input_common.rs b/src/input_common.rs index 20b4124ec..27f7ff5aa 100644 --- a/src/input_common.rs +++ b/src/input_common.rs @@ -123,6 +123,7 @@ pub enum ReadlineCmd { DeleteOrExit, Exit, CancelCommandline, + CancelCommandlineTraditional, Cancel, Undo, Redo, diff --git a/src/reader.rs b/src/reader.rs index f9550b829..59f8b8365 100644 --- a/src/reader.rs +++ b/src/reader.rs @@ -87,6 +87,7 @@ use crate::kill::{kill_add, kill_replace, kill_yank, kill_yank_rotate}; use crate::libc::MB_CUR_MAX; use crate::nix::isatty; use crate::operation_context::{get_bg_context, OperationContext}; +use crate::output::parse_color; use crate::output::Outputter; use crate::pager::{PageRendering, Pager, SelectionMotion}; use crate::panic::AT_EXIT; @@ -2305,7 +2306,7 @@ impl<'a> Reader<'a> { self.data .update_buff_pos(EditableLineTag::Commandline, Some(self.command_line_len())); } - rl::CancelCommandline => { + rl::CancelCommandline | rl::CancelCommandlineTraditional => { if self.conf.exit_on_interrupt { self.parser .set_last_statuses(Statuses::just(STATUS_CMD_ERROR.unwrap())); @@ -2315,10 +2316,37 @@ impl<'a> Reader<'a> { if self.command_line.is_empty() { return; } + if c == rl::CancelCommandlineTraditional { + // Move cursor to the end of the line. + let end = self.command_line.len(); + self.update_buff_pos(EditableLineTag::Commandline, Some(end)); + self.autosuggestion.clear(); + // Repaint also changes the actual cursor position + if self.is_repaint_needed(None) { + self.layout_and_repaint(L!("cancel")); + } + + let mut outp = Outputter::stdoutput().borrow_mut(); + if let Some(fish_color_cancel) = self.vars().get(L!("fish_color_cancel")) { + outp.set_color( + parse_color(&fish_color_cancel, false), + parse_color(&fish_color_cancel, true), + ); + } + outp.write_wstr(L!("^C")); + outp.set_color(RgbColor::RESET, RgbColor::RESET); + + // We print a newline last so the prompt_sp hack doesn't get us. + outp.push(b'\n'); + } self.push_edit( EditableLineTag::Commandline, Edit::new(0..self.command_line_len(), L!("").to_owned()), ); + if c == rl::CancelCommandlineTraditional { + self.screen + .reset_abandoning_line(usize::try_from(termsize_last().width).unwrap()); + } // Post fish_cancel. event::fire_generic(self.parser, L!("fish_cancel").to_owned(), vec![]); @@ -5002,6 +5030,7 @@ fn command_ends_paging(c: ReadlineCmd, focused_on_search_field: bool) -> bool { | rl::AcceptAutosuggestion | rl::DeleteOrExit | rl::CancelCommandline + | rl::CancelCommandlineTraditional | rl::Cancel => // These commands always end paging. {