From 9f2cc4df3653eac65b48f845ef85f68b47e709fe Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Sun, 12 Jun 2022 12:29:41 -0700 Subject: [PATCH] Save the screen status more often The fix for #3481 caused us to save the screen status after external commands were run, fixing an unnecessary abandon-line when switching modes. But we may also run commands not directly as part of a binding, but instead via an on-variable event, e.g. for fish_bind_mode. Extend this fix to all bindings, guarded by changes to exec_count. Now any time an external command runs as part of a binding we should pick up changes to the tty and not abandon the line. Fixes #3481 again. --- CHANGELOG.rst | 2 +- src/reader.cpp | 22 ++++++++++++++++++---- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 79b56bbb9..0042108b7 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -95,7 +95,7 @@ Interactive improvements - ``time`` now emits an error if used after the first command in a pipeline (:issue:`8841`). - ``fish_add_path`` now prints a message for skipped non-existent paths when using the ``-v`` flag (:issue:`8884`). - Since fish 3.2.0, pressing :kbd:`Control-D` while a command is running would end up inserting a space into the next commandline, which has been fixed (:issue:`8871`). -- A bug that caused multi-line prompts to be moved down a line when switching between insert and normal mode has been fixed (:issue:`3481`). +- A bug that caused multi-line prompts to be moved down a line when pasting or switching modes has been fixed (:issue:`3481`). - The web-based configuration system no longer strips too many quotes in the abbreviation display (:issue:`8917`, :issue:`8918`). - Fish started with ``--no-config`` will now use the default keybindings (:issue:`8493`) - When fish inherits a $USER value that doesn't correspond to the euid, it will now correct it in all cases instead of just when euid is 0 (:issue:`8879`, :issue:`8583`). diff --git a/src/reader.cpp b/src/reader.cpp index 34d29de7d..785f680f8 100644 --- a/src/reader.cpp +++ b/src/reader.cpp @@ -738,6 +738,9 @@ class reader_data_t : public std::enable_shared_from_this { parser_t &parser() { return *parser_ref; } const parser_t &parser() const { return *parser_ref; } + /// Convenience cover over exec_count(). + uint64_t exec_count() const { return parser().libdata().exec_count; } + reader_data_t(std::shared_ptr parser, std::shared_ptr hist, reader_config_t &&conf) : conf(std::move(conf)), @@ -3079,10 +3082,6 @@ void reader_data_t::run_input_command_scripts(const wcstring_list_t &cmds) { wperror(L"tcsetattr"); } termsize_container_t::shared().invalidate_tty(); - - // The input command scripts may have changed our tty - ignore any such changes. - // See #3481. - screen.save_status(); } /// Read normal characters, inserting them into the command line. @@ -3098,6 +3097,10 @@ maybe_t reader_data_t::read_normal_chars(readline_loop_state_t &rl }; command_handler_t empty_handler = {}; + // We repaint our prompt if fstat reports the tty as having changed. + // But don't react to tty changes that we initiated, because of commands or + // on-variable events (e.g. for fish_bind_mode). See #3481. + uint64_t last_exec_count = exec_count(); while (accumulated_chars.size() < limit) { bool allow_commands = (accumulated_chars.empty()); auto evt = inputter.read_char(allow_commands ? normal_handler : empty_handler); @@ -3111,6 +3114,11 @@ maybe_t reader_data_t::read_normal_chars(readline_loop_state_t &rl } else { accumulated_chars.push_back(evt.get_char()); } + + if (last_exec_count != exec_count()) { + last_exec_count = exec_count(); + screen.save_status(); + } } if (!accumulated_chars.empty()) { @@ -3125,6 +3133,12 @@ maybe_t reader_data_t::read_normal_chars(readline_loop_state_t &rl // Since we handled a normal character, we don't have a last command. rls.last_cmd.reset(); } + + if (last_exec_count != exec_count()) { + last_exec_count = exec_count(); + screen.save_status(); + } + return event_needing_handling; }