diff --git a/src/input.cpp b/src/input.cpp index b0606fb7c..3e95fb1f9 100644 --- a/src/input.cpp +++ b/src/input.cpp @@ -751,19 +751,11 @@ char_event_t inputter_t::read_char(const command_handler_t &command_handler) { } case readline_cmd_t::func_and: case readline_cmd_t::func_or: { - // If previous function has correct status, we keep reading tokens - if (evt.get_readline() == readline_cmd_t::func_and) { - // Don't return immediately, we might need to handle it here - like - // self-insert. - if (function_status_) continue; - } else { - if (!function_status_) continue; + // If previous function has bad status, we want to skip all functions that + // follow us. + if ((evt.get_readline() == readline_cmd_t::func_and) != function_status_) { + drop_leading_readline_events(); } - // Else we flush remaining tokens - do { - evt = this->readch(); - } while (evt.is_readline()); - this->push_front(evt); continue; } default: { diff --git a/src/input_common.cpp b/src/input_common.cpp index 1f9b4db2d..8087cec4d 100644 --- a/src/input_common.cpp +++ b/src/input_common.cpp @@ -285,6 +285,12 @@ void input_event_queue_t::promote_interruptions_to_front() { std::rotate(queue_.begin(), first, last); } +void input_event_queue_t::drop_leading_readline_events() { + queue_.erase(queue_.begin(), + std::find_if(queue_.begin(), queue_.end(), + [](const char_event_t& evt) { return !evt.is_readline(); })); +} + void input_event_queue_t::prepare_to_select() {} void input_event_queue_t::select_interrupted() {} void input_event_queue_t::uvar_change_notified() {} diff --git a/src/input_common.h b/src/input_common.h index 976eb1d16..ecbf3966f 100644 --- a/src/input_common.h +++ b/src/input_common.h @@ -224,6 +224,9 @@ class input_event_queue_t { queue_.insert(queue_.begin(), begin, end); } + /// Forget all enqueued readline events in the front of the queue. + void drop_leading_readline_events(); + /// Override point for when we are about to (potentially) block in select(). The default does /// nothing. virtual void prepare_to_select();