mirror of
https://github.com/fish-shell/fish-shell.git
synced 2024-11-29 05:03:46 +08:00
fix handling input in the C locale
In the C/POSIX locale EOF on the tty wasn't handled correctly due to a change a few months ago to fix an unrelated problem with that locale. What is surprising is that the core fish code doesn't explicitly depend on input_common_readch returning WEOF if a character isn't seen within `wait_on_escape_ms` after an escape. Fixes #3214
This commit is contained in:
parent
2a119ff082
commit
f3e93f0666
4
po/de.po
4
po/de.po
|
@ -1291,8 +1291,8 @@ msgstr ""
|
||||||
|
|
||||||
#: reader.cpp:4115
|
#: reader.cpp:4115
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Unknown keybinding %d"
|
msgid "Unknown key binding 0x%X"
|
||||||
msgstr "Unbekannte Tastenkombination %d"
|
msgstr "Unbekannte Tastenkombination 0x%X"
|
||||||
|
|
||||||
#: reader.cpp:4226
|
#: reader.cpp:4226
|
||||||
#, fuzzy
|
#, fuzzy
|
||||||
|
|
4
po/en.po
4
po/en.po
|
@ -1284,8 +1284,8 @@ msgstr ""
|
||||||
|
|
||||||
#: reader.cpp:4115
|
#: reader.cpp:4115
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Unknown keybinding %d"
|
msgid "Unknown key binding 0x%X"
|
||||||
msgstr "Unknown keybinding %d"
|
msgstr "Unknown key binding 0x%X"
|
||||||
|
|
||||||
#: reader.cpp:4226
|
#: reader.cpp:4226
|
||||||
msgid "Error while reading from file descriptor"
|
msgid "Error while reading from file descriptor"
|
||||||
|
|
4
po/fr.po
4
po/fr.po
|
@ -1306,8 +1306,8 @@ msgstr ""
|
||||||
|
|
||||||
#: reader.cpp:4115
|
#: reader.cpp:4115
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Unknown keybinding %d"
|
msgid "Unknown key binding 0x%X"
|
||||||
msgstr "Raccourci clavier inconnu %d"
|
msgstr "Raccourci clavier inconnu 0x%X"
|
||||||
|
|
||||||
#: reader.cpp:4226
|
#: reader.cpp:4226
|
||||||
#, fuzzy
|
#, fuzzy
|
||||||
|
|
|
@ -1306,8 +1306,8 @@ msgstr ""
|
||||||
|
|
||||||
#: reader.cpp:4115
|
#: reader.cpp:4115
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Unknown keybinding %d"
|
msgid "Unknown key binding 0x%X"
|
||||||
msgstr "Atalho desconhecido %d"
|
msgstr "Atalho desconhecido 0x%X"
|
||||||
|
|
||||||
#: reader.cpp:4226
|
#: reader.cpp:4226
|
||||||
msgid "Error while reading from file descriptor"
|
msgid "Error while reading from file descriptor"
|
||||||
|
|
4
po/sv.po
4
po/sv.po
|
@ -1295,8 +1295,8 @@ msgstr ""
|
||||||
|
|
||||||
#: reader.cpp:4115
|
#: reader.cpp:4115
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Unknown keybinding %d"
|
msgid "Unknown key binding 0x%X"
|
||||||
msgstr "Okänd tangentbordsbindning %d"
|
msgstr "Okänd tangentbords binding 0x%X"
|
||||||
|
|
||||||
#: reader.cpp:4226
|
#: reader.cpp:4226
|
||||||
msgid "Error while reading from file descriptor"
|
msgid "Error while reading from file descriptor"
|
||||||
|
|
|
@ -1273,8 +1273,8 @@ msgstr ""
|
||||||
|
|
||||||
#: reader.cpp:4115
|
#: reader.cpp:4115
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Unknown keybinding %d"
|
msgid "Unknown key binding 0x%X"
|
||||||
msgstr "Unknown keybinding %d"
|
msgstr "Unknown key binding 0x%X"
|
||||||
|
|
||||||
#: reader.cpp:4226
|
#: reader.cpp:4226
|
||||||
msgid "Error while reading from file descriptor"
|
msgid "Error while reading from file descriptor"
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <wchar.h>
|
#include <wchar.h>
|
||||||
#include <wctype.h>
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
@ -203,7 +202,7 @@ static void process_input(bool continuous_mode) {
|
||||||
fprintf(stderr, "Press a key\n\n");
|
fprintf(stderr, "Press a key\n\n");
|
||||||
while (keep_running) {
|
while (keep_running) {
|
||||||
wchar_t wc = input_common_readch(true);
|
wchar_t wc = input_common_readch(true);
|
||||||
if (wc == WEOF) {
|
if (wc == R_TIMEOUT || wc == R_EOF) {
|
||||||
output_bind_command(bind_chars);
|
output_bind_command(bind_chars);
|
||||||
if (first_char_seen && !continuous_mode) {
|
if (first_char_seen && !continuous_mode) {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -419,7 +419,7 @@ void input_function_push_args(int code) {
|
||||||
wchar_t arg;
|
wchar_t arg;
|
||||||
|
|
||||||
// Skip and queue up any function codes. See issue #2357.
|
// Skip and queue up any function codes. See issue #2357.
|
||||||
while (((arg = input_common_readch(0)) >= R_MIN) && (arg <= R_MAX)) {
|
while ((arg = input_common_readch(0)) >= R_MIN && arg <= R_MAX) {
|
||||||
skipped.push_back(arg);
|
skipped.push_back(arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -497,7 +497,7 @@ static bool input_mapping_is_match(const input_mapping_t &m) {
|
||||||
wint_t c = 0;
|
wint_t c = 0;
|
||||||
int j;
|
int j;
|
||||||
|
|
||||||
// debug(0, L"trying mapping %ls\n", escape(m.seq.c_str(), ESCAPE_ALL).c_str());
|
debug(2, L"trying to match mapping %ls", escape(m.seq.c_str(), ESCAPE_ALL).c_str());
|
||||||
const wchar_t *str = m.seq.c_str();
|
const wchar_t *str = m.seq.c_str();
|
||||||
for (j = 0; str[j] != L'\0'; j++) {
|
for (j = 0; str[j] != L'\0'; j++) {
|
||||||
bool timed = (j > 0 && iswcntrl(str[0]));
|
bool timed = (j > 0 && iswcntrl(str[0]));
|
||||||
|
@ -515,7 +515,8 @@ static bool input_mapping_is_match(const input_mapping_t &m) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the read characters.
|
// Reinsert the chars we read to be read again since we didn't match the bind sequence (i.e.,
|
||||||
|
// the input mapping).
|
||||||
input_common_next_ch(c);
|
input_common_next_ch(c);
|
||||||
for (int k = j - 1; k >= 0; k--) {
|
for (int k = j - 1; k >= 0; k--) {
|
||||||
input_common_next_ch(m.seq[k]);
|
input_common_next_ch(m.seq[k]);
|
||||||
|
@ -554,9 +555,11 @@ static void input_mapping_execute_matching_or_generic(bool allow_commands) {
|
||||||
if (generic) {
|
if (generic) {
|
||||||
input_mapping_execute(*generic, allow_commands);
|
input_mapping_execute(*generic, allow_commands);
|
||||||
} else {
|
} else {
|
||||||
// debug(0, L"no generic found, ignoring...");
|
debug(2, L"no generic found, ignoring char...");
|
||||||
wchar_t c = input_common_readch(0);
|
wchar_t c = input_common_readch(0);
|
||||||
if (c == R_EOF) input_common_next_ch(c);
|
if (c == R_EOF) {
|
||||||
|
input_common_next_ch(c);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,8 +16,6 @@
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <wchar.h>
|
#include <wchar.h>
|
||||||
#include <wctype.h>
|
|
||||||
#include <cwctype>
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
@ -35,7 +33,7 @@
|
||||||
static int wait_on_escape_ms = WAIT_ON_ESCAPE_DEFAULT;
|
static int wait_on_escape_ms = WAIT_ON_ESCAPE_DEFAULT;
|
||||||
|
|
||||||
/// Characters that have been read and returned by the sequence matching code.
|
/// Characters that have been read and returned by the sequence matching code.
|
||||||
static std::deque<wint_t> lookahead_list;
|
static std::deque<wchar_t> lookahead_list;
|
||||||
|
|
||||||
// Queue of pairs of (function pointer, argument) to be invoked. Expected to be mostly empty.
|
// Queue of pairs of (function pointer, argument) to be invoked. Expected to be mostly empty.
|
||||||
typedef std::pair<void (*)(void *), void *> callback_info_t;
|
typedef std::pair<void (*)(void *), void *> callback_info_t;
|
||||||
|
@ -203,7 +201,7 @@ wchar_t input_common_readch(int timed) {
|
||||||
struct timeval tm = {wait_on_escape_ms / 1000, 1000 * (wait_on_escape_ms % 1000)};
|
struct timeval tm = {wait_on_escape_ms / 1000, 1000 * (wait_on_escape_ms % 1000)};
|
||||||
int count = select(1, &fds, 0, 0, &tm);
|
int count = select(1, &fds, 0, 0, &tm);
|
||||||
if (count <= 0) {
|
if (count <= 0) {
|
||||||
return WEOF;
|
return R_TIMEOUT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -213,12 +211,12 @@ wchar_t input_common_readch(int timed) {
|
||||||
while (1) {
|
while (1) {
|
||||||
wint_t b = readb();
|
wint_t b = readb();
|
||||||
|
|
||||||
if (MB_CUR_MAX == 1) // single-byte locale, all values are legal
|
if (b >= R_NULL && b <= R_MAX) return b;
|
||||||
{
|
|
||||||
return (unsigned char)b;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((b >= R_NULL) && (b < R_NULL + 1000)) return b;
|
if (MB_CUR_MAX == 1) {
|
||||||
|
// return (unsigned char)b; // single-byte locale, all values are legal
|
||||||
|
return b; // single-byte locale, all values are legal
|
||||||
|
}
|
||||||
|
|
||||||
char bb = b;
|
char bb = b;
|
||||||
size_t sz = mbrtowc(&res, &bb, 1, &state);
|
size_t sz = mbrtowc(&res, &bb, 1, &state);
|
||||||
|
@ -240,7 +238,7 @@ wchar_t input_common_readch(int timed) {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!timed) {
|
if (!timed) {
|
||||||
while (has_lookahead() && lookahead_front() == WEOF) lookahead_pop();
|
while (has_lookahead() && lookahead_front() == R_TIMEOUT) lookahead_pop();
|
||||||
if (!has_lookahead()) return input_common_readch(0);
|
if (!has_lookahead()) return input_common_readch(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -70,6 +70,7 @@ enum {
|
||||||
R_BACKWARD_JUMP,
|
R_BACKWARD_JUMP,
|
||||||
R_AND,
|
R_AND,
|
||||||
R_CANCEL,
|
R_CANCEL,
|
||||||
|
R_TIMEOUT, // we didn't get interactive input within wait_on_escape_ms
|
||||||
R_MAX = R_CANCEL,
|
R_MAX = R_CANCEL,
|
||||||
// This is a special psuedo-char that is not used other than to mark the end of the the special
|
// This is a special psuedo-char that is not used other than to mark the end of the the special
|
||||||
// characters so we can sanity check the enum range.
|
// characters so we can sanity check the enum range.
|
||||||
|
@ -92,7 +93,7 @@ void set_wait_on_escape_ms(int ms);
|
||||||
/// convert them to a wchar_t. Conversion is done using mbrtowc. If a character has previously been
|
/// convert them to a wchar_t. Conversion is done using mbrtowc. If a character has previously been
|
||||||
/// read and then 'unread' using \c input_common_unreadch, that character is returned. If timed is
|
/// read and then 'unread' using \c input_common_unreadch, that character is returned. If timed is
|
||||||
/// true, readch2 will wait at most WAIT_ON_ESCAPE milliseconds for a character to be available for
|
/// true, readch2 will wait at most WAIT_ON_ESCAPE milliseconds for a character to be available for
|
||||||
/// reading before returning with the value WEOF.
|
/// reading before returning with the value R_EOF.
|
||||||
wchar_t input_common_readch(int timed);
|
wchar_t input_common_readch(int timed);
|
||||||
|
|
||||||
/// Enqueue a character or a readline function to the queue of unread characters that input_readch
|
/// Enqueue a character or a readline function to the queue of unread characters that input_readch
|
||||||
|
|
|
@ -3250,7 +3250,7 @@ const wchar_t *reader_readline(int nchars) {
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
// Other, if a normal character, we add it to the command.
|
// Other, if a normal character, we add it to the command.
|
||||||
if ((!wchar_private(c)) && (((c > 31) || (c == L'\n')) && (c != 127))) {
|
if (!wchar_private(c) && (c >= L' ' || c == L'\n' || c == L'\r') && c != 0x7F) {
|
||||||
bool allow_expand_abbreviations = false;
|
bool allow_expand_abbreviations = false;
|
||||||
if (data->is_navigating_pager_contents()) {
|
if (data->is_navigating_pager_contents()) {
|
||||||
data->pager.set_search_field_shown(true);
|
data->pager.set_search_field_shown(true);
|
||||||
|
@ -3266,11 +3266,10 @@ const wchar_t *reader_readline(int nchars) {
|
||||||
if (el == &data->command_line) {
|
if (el == &data->command_line) {
|
||||||
clear_pager();
|
clear_pager();
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// Low priority debug message. These can happen if the user presses an unefined
|
// This can happen if the user presses a control char we don't recognize. No
|
||||||
// control sequnece. No reason to report.
|
// reason to report this to the user unless they've enabled debugging output.
|
||||||
debug(2, _(L"Unknown keybinding %d"), c);
|
debug(2, _(L"Unknown key binding 0x%X"), c);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user