mirror of
https://github.com/fish-shell/fish-shell
synced 2025-01-13 13:39:02 +00:00
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
This commit is contained in:
parent
3559f20c8f
commit
32936b0eb9
6 changed files with 48 additions and 33 deletions
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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 */
|
||||
|
|
24
input.cpp
24
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
|
||||
|
|
4
input.h
4
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);
|
||||
|
||||
|
||||
/**
|
||||
|
|
|
@ -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<wint_t, std::vector<wint_t> > lookahead_list;
|
||||
static std::deque<wint_t> lookahead_list;
|
||||
|
||||
/* Queue of pairs of (function pointer, argument) to be invoked. Expected to be mostly empty. */
|
||||
typedef std::pair<void (*)(void *), void *> 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)
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue