mirror of
https://github.com/fish-shell/fish-shell
synced 2025-01-15 22:44:01 +00:00
Switch the interrupt handler from a global to an instance variable
"The" interrupt handler is used when we get a signal while waiting at the prompt. Switch it from a global function pointer to an std::function. This is a mild refactoring which itself will be replaced soon.
This commit is contained in:
parent
060ce4f7da
commit
78147abe8a
4 changed files with 49 additions and 40 deletions
|
@ -272,28 +272,6 @@ void input_mapping_set_t::add(wcstring sequence, const wchar_t *command, const w
|
|||
input_mapping_set_t::add(std::move(sequence), &command, 1, mode, sets_mode, user);
|
||||
}
|
||||
|
||||
/// Handle interruptions to key reading by reaping finished jobs and propagating the interrupt to
|
||||
/// the reader.
|
||||
static maybe_t<char_event_t> interrupt_handler() {
|
||||
// Fire any pending events.
|
||||
// TODO: eliminate this principal_parser().
|
||||
auto &parser = parser_t::principal_parser();
|
||||
event_fire_delayed(parser);
|
||||
// Reap stray processes, including printing exit status messages.
|
||||
// TODO: shouldn't need this parser here.
|
||||
if (job_reap(parser, true)) reader_schedule_prompt_repaint();
|
||||
// Tell the reader an event occurred.
|
||||
if (reader_reading_interrupted()) {
|
||||
auto vintr = shell_modes.c_cc[VINTR];
|
||||
if (vintr == 0) {
|
||||
return none();
|
||||
}
|
||||
return char_event_t{vintr};
|
||||
}
|
||||
|
||||
return char_event_t{char_event_type_t::check_exit};
|
||||
}
|
||||
|
||||
static relaxed_atomic_bool_t s_input_initialized{false};
|
||||
|
||||
/// Set up arrays used by readch to detect escape sequences for special keys and perform related
|
||||
|
@ -303,7 +281,6 @@ void init_input() {
|
|||
if (s_input_initialized) return;
|
||||
s_input_initialized = true;
|
||||
|
||||
input_common_init(&interrupt_handler);
|
||||
s_terminfo_mappings = create_input_terminfo();
|
||||
|
||||
auto input_mapping = input_mappings();
|
||||
|
@ -338,7 +315,35 @@ void init_input() {
|
|||
}
|
||||
}
|
||||
|
||||
inputter_t::inputter_t(parser_t &parser, int in) : event_queue_(in), parser_(parser.shared()) {}
|
||||
inputter_t::inputter_t(parser_t &parser, int in)
|
||||
: parser_(parser.shared()), event_queue_(in, get_interrupt_handler()) {}
|
||||
|
||||
/// Handle interruptions to key reading by reaping finished jobs and propagating the interrupt to
|
||||
/// the reader.
|
||||
maybe_t<char_event_t> inputter_t::handle_interrupt() {
|
||||
// Fire any pending events.
|
||||
auto &parser = *this->parser_;
|
||||
event_fire_delayed(parser);
|
||||
// Reap stray processes, including printing exit status messages.
|
||||
if (job_reap(parser, true)) reader_schedule_prompt_repaint();
|
||||
// Tell the reader an event occurred.
|
||||
if (reader_reading_interrupted()) {
|
||||
auto vintr = shell_modes.c_cc[VINTR];
|
||||
if (vintr == 0) {
|
||||
return none();
|
||||
}
|
||||
return char_event_t{vintr};
|
||||
}
|
||||
|
||||
return char_event_t{char_event_type_t::check_exit};
|
||||
}
|
||||
|
||||
interrupt_handler_t inputter_t::get_interrupt_handler() {
|
||||
// It's OK to capture 'this' by value because we use this to populate one of our instance
|
||||
// variables.
|
||||
interrupt_handler_t func = [this] { return this->handle_interrupt(); };
|
||||
return func;
|
||||
}
|
||||
|
||||
void inputter_t::function_push_arg(wchar_t arg) { input_function_args_.push_back(arg); }
|
||||
|
||||
|
|
|
@ -57,12 +57,17 @@ class inputter_t {
|
|||
wchar_t function_pop_arg();
|
||||
|
||||
private:
|
||||
// We need a parser to evaluate bindings.
|
||||
const std::shared_ptr<parser_t> parser_;
|
||||
|
||||
input_event_queue_t event_queue_;
|
||||
std::vector<wchar_t> input_function_args_{};
|
||||
bool function_status_{false};
|
||||
|
||||
// We need a parser to evaluate bindings.
|
||||
const std::shared_ptr<parser_t> parser_;
|
||||
// A function called when select() is interrupted by a signal.
|
||||
// See interrupt_handler_t.
|
||||
maybe_t<char_event_t> handle_interrupt();
|
||||
interrupt_handler_t get_interrupt_handler();
|
||||
|
||||
void function_push_arg(wchar_t arg);
|
||||
void function_push_args(readline_cmd_t code);
|
||||
|
|
|
@ -36,10 +36,8 @@
|
|||
#define WAIT_ON_ESCAPE_DEFAULT 30
|
||||
static int wait_on_escape_ms = WAIT_ON_ESCAPE_DEFAULT;
|
||||
|
||||
/// Callback function for handling interrupts on reading.
|
||||
static interrupt_func_t interrupt_handler;
|
||||
|
||||
void input_common_init(interrupt_func_t func) { interrupt_handler = func; }
|
||||
input_event_queue_t::input_event_queue_t(int in, interrupt_handler_t handler)
|
||||
: in_(in), interrupt_handler_(std::move(handler)) {}
|
||||
|
||||
/// Internal function used by input_common_readch to read one byte from fd 0. This function should
|
||||
/// only be called by input_common_readch().
|
||||
|
@ -73,8 +71,8 @@ char_event_t input_event_queue_t::readb() {
|
|||
if (notifier.poll()) {
|
||||
env_universal_barrier();
|
||||
}
|
||||
if (interrupt_handler) {
|
||||
if (auto interrupt_evt = interrupt_handler()) {
|
||||
if (interrupt_handler_) {
|
||||
if (auto interrupt_evt = interrupt_handler_()) {
|
||||
return *interrupt_evt;
|
||||
} else if (auto mc = try_pop()) {
|
||||
return *mc;
|
||||
|
|
|
@ -176,21 +176,19 @@ class char_event_t {
|
|||
}
|
||||
};
|
||||
|
||||
/// A type of function invoked on interrupt.
|
||||
/// \return the event which is to be returned to the reader loop, or none if VINTR is 0.
|
||||
using interrupt_func_t = maybe_t<char_event_t> (*)();
|
||||
|
||||
/// Init the library with an interrupt function.
|
||||
void input_common_init(interrupt_func_t func);
|
||||
|
||||
/// Adjust the escape timeout.
|
||||
class environment_t;
|
||||
void update_wait_on_escape_ms(const environment_t& vars);
|
||||
|
||||
/// A function type called when select() is interrupted by a signal.
|
||||
/// The function maybe returns an event which is propagated back to the caller.
|
||||
using interrupt_handler_t = std::function<maybe_t<char_event_t>()>;
|
||||
|
||||
/// A class which knows how to produce a stream of input events.
|
||||
class input_event_queue_t {
|
||||
public:
|
||||
explicit input_event_queue_t(int in = 0) : in_(in) {}
|
||||
/// Construct from a file descriptor \p in, and an interrupt handler \p handler.
|
||||
explicit input_event_queue_t(int in = STDIN_FILENO, interrupt_handler_t handler = {});
|
||||
|
||||
/// Function used by input_readch to read bytes from stdin until enough bytes have been read to
|
||||
/// convert them to a wchar_t. Conversion is done using mbrtowc. If a character has previously
|
||||
|
@ -225,9 +223,12 @@ class input_event_queue_t {
|
|||
/// \return the next event in the queue, or none if the queue is empty.
|
||||
maybe_t<char_event_t> try_pop();
|
||||
|
||||
/// Read at most one byte from stdin, and return the event.
|
||||
/// If select() is interrupted by a signal, then invoke the interrupt handler.
|
||||
char_event_t readb();
|
||||
|
||||
int in_{0};
|
||||
const interrupt_handler_t interrupt_handler_;
|
||||
std::deque<char_event_t> queue_;
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue