From 179073ce623c0ce06392cc5e0b81768b6db6553c Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Sun, 11 Jul 2021 16:50:21 -0700 Subject: [PATCH] Clear the control-C cancel flag earlier, allowing event handlers to run When the user presses control-C, fish marks a cancellation signal which prevents fish script from running, allowing it to properly unwind. Prior to this commit, the signal was cleared in the reader. However this missed the case where a binding would set $fish_bind_mode which would trigger event handlers: the event handlers would be skipped because of the cancellation flag was still set. This is similar to #6937. Let's clear the flag earlier, as soon as we it's set, in inputter_t. Fixes #8125. --- CHANGELOG.rst | 1 + src/input.cpp | 4 ++++ src/reader.cpp | 7 +------ tests/pexpects/bind_mode_events.py | 20 ++++++++++++++++++++ 4 files changed, 26 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 7aaf31ec1..7a84c8858 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -13,6 +13,7 @@ Scripting improvements Interactive improvements ------------------------ +Vi mode cursors are now set properly after control-C. (:issue:`8125`). New or improved bindings ^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/input.cpp b/src/input.cpp index f1c2f9fed..fb6d66a34 100644 --- a/src/input.cpp +++ b/src/input.cpp @@ -329,6 +329,10 @@ void inputter_t::prepare_to_select() /* override */ { } void inputter_t::select_interrupted() /* override */ { + // Readline commands may be bound to \cc which also sets the cancel flag. + // See #6937, #8125. + signal_clear_cancel(); + // Fire any pending events and reap stray processes, including printing exit status messages. auto &parser = *this->parser_; event_fire_delayed(parser); diff --git a/src/reader.cpp b/src/reader.cpp index dc88fe4b5..0a170153a 100644 --- a/src/reader.cpp +++ b/src/reader.cpp @@ -2943,8 +2943,7 @@ void reader_data_t::handle_readline_command(readline_cmd_t c, readline_loop_stat set_command_line_and_position(&command_line, L"", 0); s_reset_abandoning_line(&screen, termsize_last().width - command_line.size()); - // Post fish_cancel, allowing it to fire. - signal_clear_cancel(); + // Post fish_cancel. event_fire_generic(parser(), L"fish_cancel"); } break; @@ -3977,10 +3976,6 @@ maybe_t reader_data_t::readline(int nchars_or_0) { history_search.reset(); } - // Readline commands may be bound to \cc which also sets the cancel flag. - // See #6937. - signal_clear_cancel(); - rls.last_cmd = readline_cmd; } else { // Ordinary char. diff --git a/tests/pexpects/bind_mode_events.py b/tests/pexpects/bind_mode_events.py index 0cda01cef..e721a57f3 100644 --- a/tests/pexpects/bind_mode_events.py +++ b/tests/pexpects/bind_mode_events.py @@ -1,5 +1,7 @@ #!/usr/bin/env python3 from pexpect_helper import SpawnedProc +import os +import signal sp = SpawnedProc() send, sendline, sleep, expect_prompt = sp.send, sp.sendline, sp.sleep, sp.expect_prompt @@ -33,3 +35,21 @@ sleep(0.050) send("echo mode changes: $MODE_CHANGES\r") expect_prompt("\r\nmode changes: default insert default insert\r\n") + +# Regression test for #8125. +# Control-C should return us to insert mode. +send("set -e MODE_CHANGES\r") +expect_prompt() + +# Put some text on the command line and then go back to normal mode. +send("echo stuff") +sp.expect_str("echo stuff") +send("\033") +sleep(0.050) + +os.kill(sp.spawn.pid, signal.SIGINT) +sleep(0.050) + +# We should be back in insert mode now. +send("echo mode changes: $MODE_CHANGES\r") +expect_prompt("\r\nmode changes: default insert\r\n")