From 32936b0eb95c9cee54d3887328e4bfd01c961922 Mon Sep 17 00:00:00 2001 From: Sanne Wouda Date: Sun, 5 Apr 2015 20:07:17 +0200 Subject: [PATCH] Change lookahead_list into a queue Using builtin `commandline -f`, one would expect to have commands executed in the order that they were given. This motivates the change to a queue. Unfortunately, fish internals still need lookahead_list to act as a stack. Add and rename functions to support both cases and have lookahead_list as a std::deque internally. This code is delicate, and we should probably dog-food this in nightly for a while before the next-minor release. Fixes #1567 --- builtin_commandline.cpp | 4 ++-- fish_tests.cpp | 8 +++----- input.cpp | 24 ++++++++++++------------ input.h | 4 ++-- input_common.cpp | 30 ++++++++++++++++++++---------- input_common.h | 11 +++++++++-- 6 files changed, 48 insertions(+), 33 deletions(-) diff --git a/builtin_commandline.cpp b/builtin_commandline.cpp index 7f576aff7..339cb0d14 100644 --- a/builtin_commandline.cpp +++ b/builtin_commandline.cpp @@ -455,10 +455,10 @@ static int builtin_commandline(parser_t &parser, wchar_t **argv) { /* input_unreadch inserts the specified keypress or - readline function at the top of the stack of unused + readline function at the back of the queue of unused keypresses */ - input_unreadch(c); + input_queue_ch(c); } else { diff --git a/fish_tests.cpp b/fish_tests.cpp index 982997d36..e3615ebaa 100644 --- a/fish_tests.cpp +++ b/fish_tests.cpp @@ -2389,11 +2389,9 @@ static void test_input() input_mapping_add(prefix_binding.c_str(), L"up-line"); input_mapping_add(desired_binding.c_str(), L"down-line"); - /* Push the desired binding on the stack (backwards!) */ - size_t idx = desired_binding.size(); - while (idx--) - { - input_unreadch(desired_binding.at(idx)); + /* Push the desired binding to the queue */ + for (size_t idx = 0; idx < desired_binding.size(); idx++) { + input_queue_ch(desired_binding.at(idx)); } /* Now test */ diff --git a/input.cpp b/input.cpp index 9e1560cff..4ddf35691 100644 --- a/input.cpp +++ b/input.cpp @@ -583,7 +583,7 @@ static void input_mapping_execute(const input_mapping_t &m, bool allow_commands) wchar_t code = input_function_get_code(command); if (code != (wchar_t)-1) { - input_unreadch(code); + input_common_next_ch(code); } else if (allow_commands) { @@ -596,16 +596,16 @@ static void input_mapping_execute(const input_mapping_t &m, bool allow_commands) proc_set_last_status(last_status); - input_unreadch(R_NULL); + input_common_next_ch(R_NULL); } else { /* We don't want to run commands yet. Put the characters back and return R_NULL */ for (wcstring::const_reverse_iterator it = m.seq.rbegin(), end = m.seq.rend(); it != end; ++it) { - input_unreadch(*it); + input_common_next_ch(*it); } - input_unreadch(R_NULL); + input_common_next_ch(R_NULL); return; /* skip the input_set_bind_mode */ } } @@ -648,10 +648,10 @@ static bool input_mapping_is_match(const input_mapping_t &m) /* Return the read characters */ - input_unreadch(c); + input_common_next_ch(c); for (k=j-1; k>=0; k--) { - input_unreadch(m.seq[k]); + input_common_next_ch(m.seq[k]); } } @@ -659,9 +659,9 @@ static bool input_mapping_is_match(const input_mapping_t &m) } -void input_unreadch(wint_t ch) +void input_queue_ch(wint_t ch) { - input_common_unreadch(ch); + input_common_queue_ch(ch); } static void input_mapping_execute_matching_or_generic(bool allow_commands) @@ -679,7 +679,7 @@ static void input_mapping_execute_matching_or_generic(bool allow_commands) if (m.mode != bind_mode) { - //debug(0, L"skipping mapping because mode %ls != %ls\n", m.mode.c_str(), input_get_bind_mode()); + //debug(0, L"skipping mapping because mode %ls != %ls\n", m.mode.c_str(), input_get_bind_mode().c_str()); continue; } @@ -703,7 +703,7 @@ static void input_mapping_execute_matching_or_generic(bool allow_commands) //debug(0, L"no generic found, ignoring..."); wchar_t c = input_common_readch(0); if (c == R_EOF) - input_common_unreadch(c); + input_common_next_ch(c); } } @@ -745,7 +745,7 @@ wint_t input_readch(bool allow_commands) else { while ((c = input_common_readch(0)) && c >= R_MIN && c <= R_MAX); - input_unreadch(c); + input_common_next_ch(c); return input_readch(); } } @@ -757,7 +757,7 @@ wint_t input_readch(bool allow_commands) } else { - input_unreadch(c); + input_common_next_ch(c); input_mapping_execute_matching_or_generic(allow_commands); // regarding allow_commands, we're in a loop, but if a fish command // is executed, R_NULL is unread, so the next pass through the loop diff --git a/input.h b/input.h index 9864d7307..a3a3a076c 100644 --- a/input.h +++ b/input.h @@ -112,11 +112,11 @@ void input_destroy(); wint_t input_readch(bool allow_commands = true); /** - Push a character or a readline function onto the stack of unread + Enqueue a character or a readline function to the queue of unread characters that input_readch will return before actually reading from fd 0. */ -void input_unreadch(wint_t ch); +void input_queue_ch(wint_t ch); /** diff --git a/input_common.cpp b/input_common.cpp index 045cb8f3f..b748ca22f 100644 --- a/input_common.cpp +++ b/input_common.cpp @@ -38,7 +38,7 @@ Implementation file for the low level input library #define WAIT_ON_ESCAPE 10 /** Characters that have been read and returned by the sequence matching code */ -static std::stack > lookahead_list; +static std::deque lookahead_list; /* Queue of pairs of (function pointer, argument) to be invoked. Expected to be mostly empty. */ typedef std::pair callback_info_t; @@ -53,19 +53,24 @@ static bool has_lookahead(void) static wint_t lookahead_pop(void) { - wint_t result = lookahead_list.top(); - lookahead_list.pop(); + wint_t result = lookahead_list.front(); + lookahead_list.pop_front(); return result; } -static void lookahead_push(wint_t c) +static void lookahead_push_back(wint_t c) { - lookahead_list.push(c); + lookahead_list.push_back(c); } -static wint_t lookahead_top(void) +static void lookahead_push_front(wint_t c) { - return lookahead_list.top(); + lookahead_list.push_front(c); +} + +static wint_t lookahead_front(void) +{ + return lookahead_list.front(); } /** Callback function for handling interrupts on reading */ @@ -278,7 +283,7 @@ wchar_t input_common_readch(int timed) { if (!timed) { - while (has_lookahead() && lookahead_top() == WEOF) + while (has_lookahead() && lookahead_front() == WEOF) lookahead_pop(); if (! has_lookahead()) return input_common_readch(0); @@ -289,9 +294,14 @@ wchar_t input_common_readch(int timed) } -void input_common_unreadch(wint_t ch) +void input_common_queue_ch(wint_t ch) { - lookahead_push(ch); + lookahead_push_back(ch); +} + +void input_common_next_ch(wint_t ch) +{ + lookahead_push_front(ch); } void input_common_add_callback(void (*callback)(void *), void *arg) diff --git a/input_common.h b/input_common.h index 1041e3fe5..46430af40 100644 --- a/input_common.h +++ b/input_common.h @@ -47,11 +47,18 @@ void input_common_destroy(); wchar_t input_common_readch(int timed); /** - Push a character or a readline function onto the stack of unread + Enqueue a character or a readline function to the queue of unread characters that input_readch will return before actually reading from fd 0. */ -void input_common_unreadch(wint_t ch); +void input_common_queue_ch(wint_t ch); + +/** + Add a character or a readline function to the front of the queue of unread + characters. This will be the first character returned by input_readch + (unless this function is called more than once). +*/ +void input_common_next_ch(wint_t ch); /** Adds a callback to be invoked at the next turn of the "event loop." The callback function will be invoked and passed arg. */ void input_common_add_callback(void (*callback)(void *), void *arg);