self-insert bindings to insert their own sequence

Prior to this fix, self-insert would always wait for a new character.
Track in char_event what sequence generated the readline event, and then
if the sequence is not empty, insert that sequence.

This will support implementing the space binding via pure readline
functions.
This commit is contained in:
ridiculousfish 2019-09-21 15:57:21 -07:00
parent 1ecbe363d0
commit 18b56637f7
2 changed files with 14 additions and 3 deletions

View File

@ -377,7 +377,7 @@ void inputter_t::mapping_execute(const input_mapping_t &m, bool allow_commands)
it != end; ++it) { it != end; ++it) {
readline_cmd_t code = input_function_get_code(*it).value(); readline_cmd_t code = input_function_get_code(*it).value();
function_push_args(code); function_push_args(code);
event_queue_.push_front(code); event_queue_.push_front(char_event_t(code, m.seq));
} }
} else if (has_commands && !has_functions) { } else if (has_commands && !has_functions) {
// Execute all commands. // Execute all commands.
@ -404,7 +404,7 @@ void inputter_t::mapping_execute(const input_mapping_t &m, bool allow_commands)
bool inputter_t::mapping_is_match(const input_mapping_t &m) { bool inputter_t::mapping_is_match(const input_mapping_t &m) {
const wcstring &str = m.seq; const wcstring &str = m.seq;
assert(str.size() > 0 && "zero-length input string passed to input_mapping_is_match!"); assert(str.size() > 0 && "zero-length input string passed to mapping_is_match!");
bool timed = false; bool timed = false;
for (size_t i = 0; i < str.size(); ++i) { for (size_t i = 0; i < str.size(); ++i) {
@ -495,6 +495,11 @@ char_event_t inputter_t::readch(bool allow_commands) {
if (evt.is_readline()) { if (evt.is_readline()) {
switch (evt.get_readline()) { switch (evt.get_readline()) {
case readline_cmd_t::self_insert: { case readline_cmd_t::self_insert: {
// Typically self-insert is generated by the generic (empty) binding.
// However if it is generated by a real sequence, then insert that sequence.
for (auto iter = evt.seq.crbegin(); iter != evt.seq.crend(); ++iter) {
event_queue_.push_front(*iter);
}
// Issue #1595: ensure we only insert characters, not readline functions. The // Issue #1595: ensure we only insert characters, not readline functions. The
// common case is that this will be empty. // common case is that this will be empty.
return read_characters_no_readline(); return read_characters_no_readline();

View File

@ -105,8 +105,13 @@ class char_event_t {
} v_{}; } v_{};
public: public:
/// The type of event.
char_event_type_t type; char_event_type_t type;
/// The sequence of characters in the input mapping which generated this event.
/// Note that the generic self-insert case does not have any characters, so this would be empty.
wcstring seq{};
bool is_timeout() const { return type == char_event_type_t::timeout; } bool is_timeout() const { return type == char_event_type_t::timeout; }
bool is_char() const { return type == char_event_type_t::charc; } bool is_char() const { return type == char_event_type_t::charc; }
@ -129,7 +134,8 @@ class char_event_t {
/* implicit */ char_event_t(wchar_t c) : type(char_event_type_t::charc) { v_.c = c; } /* implicit */ char_event_t(wchar_t c) : type(char_event_type_t::charc) { v_.c = c; }
/* implicit */ char_event_t(readline_cmd_t rl) : type(char_event_type_t::readline) { /* implicit */ char_event_t(readline_cmd_t rl, wcstring seq = {})
: type(char_event_type_t::readline), seq(std::move(seq)) {
v_.rl = rl; v_.rl = rl;
} }