diff --git a/doc_src/cmds/bind.rst b/doc_src/cmds/bind.rst index dbce9f29d..e900a1d9e 100644 --- a/doc_src/cmds/bind.rst +++ b/doc_src/cmds/bind.rst @@ -98,6 +98,8 @@ The following special input functions are available: - ``cancel``, cancel the current commandline and replace it with a new empty one +- ``cancel-commandline``, cancel the current commandline and replace it with a new empty one, leaving the old one in place with a marker to show that it was cancelled + - ``capitalize-word``, make the current word begin with a capital letter - ``complete``, guess the remainder of the current token diff --git a/share/functions/__fish_shared_key_bindings.fish b/share/functions/__fish_shared_key_bindings.fish index 7a4522cab..5407ae42e 100644 --- a/share/functions/__fish_shared_key_bindings.fish +++ b/share/functions/__fish_shared_key_bindings.fish @@ -89,7 +89,7 @@ function __fish_shared_key_bindings -d "Bindings shared between emacs and vi mod # ncurses > 6.0 sends a "delete scrollback" sequence along with clear. # This string replace removes it. bind --preset $argv \cl 'echo -n (clear | string replace \e\[3J ""); commandline -f repaint' - bind --preset $argv \cc __fish_cancel_commandline + bind --preset $argv \cc cancel-commandline bind --preset $argv \cu backward-kill-line bind --preset $argv \cw backward-kill-path-component bind --preset $argv \e\[F end-of-line diff --git a/share/functions/fish_vi_key_bindings.fish b/share/functions/fish_vi_key_bindings.fish index f83bfe0a3..602a313b5 100644 --- a/share/functions/fish_vi_key_bindings.fish +++ b/share/functions/fish_vi_key_bindings.fish @@ -67,7 +67,7 @@ function fish_vi_key_bindings --description 'vi-like key bindings for fish' # Default (command) mode bind -s --preset :q exit - bind -s --preset -m insert \cc __fish_cancel_commandline + bind -s --preset -m insert \cc cancel-commandline bind -s --preset -M default h backward-char bind -s --preset -M default l forward-char bind -s --preset -m insert \n execute diff --git a/src/input.cpp b/src/input.cpp index 2ceee9f81..0e236cf1b 100644 --- a/src/input.cpp +++ b/src/input.cpp @@ -148,6 +148,7 @@ static const input_function_metadata_t input_function_metadata[] = { {readline_cmd_t::func_and, L"and"}, {readline_cmd_t::expand_abbr, L"expand-abbr"}, {readline_cmd_t::delete_or_exit, L"delete-or-exit"}, + {readline_cmd_t::cancel_commandline, L"cancel-commandline"}, {readline_cmd_t::cancel, L"cancel"}, {readline_cmd_t::undo, L"undo"}, {readline_cmd_t::redo, L"redo"}, diff --git a/src/input_common.h b/src/input_common.h index 901acf678..5401859d9 100644 --- a/src/input_common.h +++ b/src/input_common.h @@ -71,6 +71,7 @@ enum class readline_cmd_t { func_and, expand_abbr, delete_or_exit, + cancel_commandline, cancel, undo, redo, diff --git a/src/reader.cpp b/src/reader.cpp index ef2763731..05c5677f7 100644 --- a/src/reader.cpp +++ b/src/reader.cpp @@ -1174,6 +1174,7 @@ static bool command_ends_paging(readline_cmd_t c, bool focused_on_search_field) case rl::history_token_search_forward: case rl::accept_autosuggestion: case rl::delete_or_exit: + case rl::cancel_commandline: case rl::cancel: { // These commands always end paging. return true; @@ -2673,6 +2674,29 @@ void reader_data_t::handle_readline_command(readline_cmd_t c, readline_loop_stat mark_repaint_needed(); break; } + case rl::cancel_commandline: { + if (command_line.size()) { + outputter_t &outp = outputter_t::stdoutput(); + // Move cursor to the end of the line. + update_buff_pos(&command_line, command_line.size()); + // Repaint also changes the actual cursor position + repaint(); + + auto fish_color_cancel = vars.get(L"fish_color_cancel"); + if (fish_color_cancel) { + outp.set_color(parse_color(*fish_color_cancel, false), parse_color(*fish_color_cancel, true)); + } + outp.writestr(L"^C"); + outp.set_color(rgb_color_t::reset(), rgb_color_t::reset()); + + // We print a newline last so the prompt_sp hack doesn't get us. + outp.push_back('\n'); + + set_command_line_and_position(&command_line, L"", 0); + s_reset_abandoning_line(&screen, termsize_last().width - command_line.size()); + } + break; + } case rl::cancel: { // The only thing we can cancel right now is paging, which we handled up above. break;