From 00f24695fe0c4f301fa17708e97dd64837c08799 Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Sat, 16 Mar 2019 12:35:49 -0700 Subject: [PATCH] Remove R_EOF Promote R_EOF to a new char_event_type_t instead of keeping it as a char value. --- src/fish_key_reader.cpp | 10 +++++----- src/input.cpp | 18 ++++++++++-------- src/input_common.cpp | 18 ++++++++++++------ src/input_common.h | 6 +++++- src/reader.cpp | 7 +++---- 5 files changed, 35 insertions(+), 24 deletions(-) diff --git a/src/fish_key_reader.cpp b/src/fish_key_reader.cpp index 71e374fbb..ba688b4e7 100644 --- a/src/fish_key_reader.cpp +++ b/src/fish_key_reader.cpp @@ -204,14 +204,13 @@ static void process_input(bool continuous_mode) { std::fwprintf(stderr, L"Press a key\n\n"); while (keep_running) { - wchar_t wc; + char_event_t evt{0}; if (reader_test_and_clear_interrupted()) { - wc = shell_modes.c_cc[VINTR]; + evt = char_event_t{shell_modes.c_cc[VINTR]}; } else { - auto mwc = input_common_readch_timed(true); - wc = mwc.is_char() ? mwc.get_char() : R_EOF; + evt = input_common_readch_timed(true); } - if (wc == R_EOF) { + if (!evt.is_char()) { output_bind_command(bind_chars); if (first_char_seen && !continuous_mode) { return; @@ -219,6 +218,7 @@ static void process_input(bool continuous_mode) { continue; } + wchar_t wc = evt.get_char(); prev_tstamp = output_elapsed_time(prev_tstamp, first_char_seen); add_char_to_bind_command(wc, bind_chars); output_info_about_char(wc); diff --git a/src/input.cpp b/src/input.cpp index 7a00faa11..edcd02910 100644 --- a/src/input.cpp +++ b/src/input.cpp @@ -440,22 +440,24 @@ static void input_mapping_execute_matching_or_generic(bool allow_commands) { } else { debug(2, L"no generic found, ignoring char..."); auto evt = input_common_readch(); - if (evt.is_char() && evt.get_char() == R_EOF) { + if (evt.is_eof()) { input_common_next_ch(evt); } } } /// Helper function. Picks through the queue of incoming characters until we get to one that's not a -/// readline function. -static char_event_t input_read_characters_only() { +/// readline function, or EOF. +static char_event_t input_read_characters_eof_only() { std::vector saved_events; char_event_t char_to_return{0}; for (;;) { auto evt = input_common_readch(); - if (evt.is_char()) { + if (evt.is_eof()) { + return evt; + } else if (evt.is_char()) { auto c = evt.get_char(); - if (!evt.is_readline() || c == R_NULL || c == R_EOF) { + if (!evt.is_readline() || c == R_NULL) { char_to_return = evt; break; } @@ -481,7 +483,7 @@ char_event_t input_readch(bool allow_commands) { case R_SELF_INSERT: { // Issue #1595: ensure we only insert characters, not readline functions. The // common case is that this will be empty. - return input_read_characters_only(); + return input_read_characters_eof_only(); } case R_AND: { if (input_function_status) { @@ -495,8 +497,8 @@ char_event_t input_readch(bool allow_commands) { } default: { return evt; } } - } else if (evt.is_char() && evt.get_char() == R_EOF) { - // If we have R_EOF, we need to immediately quit. + } else if (evt.is_eof()) { + // If we have EOF, we need to immediately quit. // There's no need to go through the input functions. return evt; } else { diff --git a/src/input_common.cpp b/src/input_common.cpp index 8706d8a19..c72ba8c7c 100644 --- a/src/input_common.cpp +++ b/src/input_common.cpp @@ -69,7 +69,8 @@ void input_common_init(int (*ih)()) { interrupt_handler = ih; } /// Internal function used by input_common_readch to read one byte from fd 0. This function should /// only be called by input_common_readch(). -static wint_t readb() { +/// \return the char, or none() on EOF. +static maybe_t readb() { // do_loop must be set on every path through the loop; leaving it uninitialized allows the // static analyzer to assist in catching mistakes. unsigned char arr[1]; @@ -123,8 +124,8 @@ static wint_t readb() { do_loop = true; } else { - // The terminal has been closed. Save and exit. - return R_EOF; + // The terminal has been closed. + return none(); } } else { // Assume we loop unless we see a character in stdin. @@ -149,8 +150,8 @@ static wint_t readb() { if (FD_ISSET(STDIN_FILENO, &fdset)) { if (read_blocked(0, arr, 1) != 1) { - // The teminal has been closed. Save and exit. - return R_EOF; + // The teminal has been closed. + return none(); } // We read from stdin, so don't loop. @@ -189,7 +190,12 @@ char_event_t input_common_readch() { wchar_t res; mbstate_t state = {}; while (1) { - wint_t b = readb(); + auto mb = readb(); + if (!mb) { + // EOF + return char_event_type_t::eof; + } + wint_t b = *mb; if (b >= R_NULL && b < R_END_INPUT_FUNCTIONS) return b; diff --git a/src/input_common.h b/src/input_common.h index a0427e665..1c8a2db6b 100644 --- a/src/input_common.h +++ b/src/input_common.h @@ -14,7 +14,6 @@ enum { // R_NULL is sometimes returned by the input when a character was requested but none could be // delivered, or when an exception happened. R_NULL = R_MIN, - R_EOF, R_BEGINNING_OF_LINE, R_END_OF_LINE, @@ -88,6 +87,9 @@ enum class char_event_type_t { /// A timeout was hit. timeout, + + /// end-of-file was reached. + eof }; class char_event_t { @@ -101,6 +103,8 @@ class char_event_t { bool is_char() const { return type == char_event_type_t::charc; } + bool is_eof() const { return type == char_event_type_t::eof; } + bool is_readline() const { return is_char() && c_ >= R_BEGIN_INPUT_FUNCTIONS && c_ < R_END_INPUT_FUNCTIONS; } diff --git a/src/reader.cpp b/src/reader.cpp index 63b88ad36..bf2a871fb 100644 --- a/src/reader.cpp +++ b/src/reader.cpp @@ -2503,6 +2503,9 @@ maybe_t reader_data_t::readline(int nchars) { if (!event_needing_handling) { event_needing_handling = R_NULL; + } else if (event_needing_handling->is_eof()) { + reader_force_exit(); + continue; } assert(event_needing_handling->is_char() && "Should have a char event"); wchar_t c = event_needing_handling->get_char(); @@ -2577,10 +2580,6 @@ maybe_t reader_data_t::readline(int nchars) { } break; } - case R_EOF: { - reader_force_exit(); - break; - } case R_COMPLETE: case R_COMPLETE_AND_SEARCH: { if (!complete_func) break;