allow configuring the escape delay timeout

Introduce a "fish_escape_delay_ms" variable to allow the user to configure the
delay used when seeing a bare escape before assuming no other characters will
be received that might match a bound character sequence. This is primarily
useful for vi mode so that a bare escape character (i.e., keystroke) can
switch to vi "insert" to "normal" mode in a timely fashion.
This commit is contained in:
Kurtis Rader 2016-01-14 21:46:53 -08:00
parent 6969cfab3d
commit 4b9fece9f4
5 changed files with 145 additions and 54 deletions

View file

@ -303,7 +303,7 @@ static void handle_locale()
}
/** React to modifying hte given variable */
/** React to modifying the given variable */
static void react_to_variable_change(const wcstring &key)
{
if (var_is_locale(key))
@ -319,6 +319,10 @@ static void react_to_variable_change(const wcstring &key)
{
reader_react_to_color_change();
}
else if (key == L"fish_escape_delay_ms")
{
update_wait_on_escape_ms();
}
}
/**

View file

@ -33,9 +33,11 @@ Implementation file for the low level input library
reading after \\x1b is read before assuming that escape key was
pressed, and not an escape sequence.
This is the value used by the readline library.
This is the value used by the readline library. It can be overridden by
setting the fish_escape_delay_ms variable.
*/
#define WAIT_ON_ESCAPE 500
#define WAIT_ON_ESCAPE_DEFAULT 500
static int wait_on_escape_ms = WAIT_ON_ESCAPE_DEFAULT;
/** Characters that have been read and returned by the sequence matching code */
static std::deque<wint_t> lookahead_list;
@ -79,6 +81,7 @@ static int (*interrupt_handler)();
void input_common_init(int (*ih)())
{
interrupt_handler = ih;
update_wait_on_escape_ms();
}
void input_common_destroy()
@ -214,36 +217,48 @@ static wint_t readb()
return arr[0];
}
// Update the wait_on_escape_ms value in response to the fish_escape_delay_ms
// user variable being set.
void update_wait_on_escape_ms()
{
env_var_t escape_time_ms = env_get_string(L"fish_escape_delay_ms");
if (escape_time_ms.missing_or_empty())
{
wait_on_escape_ms = WAIT_ON_ESCAPE_DEFAULT;
return;
}
wchar_t *endptr;
long tmp = wcstol(escape_time_ms.c_str(), &endptr, 10);
if (*endptr != '\0' || tmp < 10 || tmp >= 5000)
{
fwprintf(stderr, L"ignoring fish_escape_delay_ms: value '%ls' "
"is not an integer or is < 10 or >= 5000 ms\n",
escape_time_ms.c_str());
}
else
{
wait_on_escape_ms = (int)tmp;
}
}
wchar_t input_common_readch(int timed)
{
if (! has_lookahead())
{
if (timed)
{
int count;
fd_set fds;
struct timeval tm=
{
0,
1000 * WAIT_ON_ESCAPE
}
;
FD_ZERO(&fds);
FD_SET(0, &fds);
count = select(1, &fds, 0, 0, &tm);
switch (count)
struct timeval tm = {wait_on_escape_ms / 1000,
1000 * (wait_on_escape_ms % 1000)};
int count = select(1, &fds, 0, 0, &tm);
if (count <= 0)
{
case 0:
return WEOF;
case -1:
return WEOF;
break;
default:
break;
return WEOF;
}
}

View file

@ -35,6 +35,9 @@ void input_common_init(int (*ih)());
*/
void input_common_destroy();
// Adjust the escape timeout.
void update_wait_on_escape_ms();
/**
Function used by input_readch to read bytes from stdin until enough
bytes have been read to convert them to a wchar_t. Conversion is

View file

@ -2,59 +2,124 @@
spawn $fish
expect_prompt
# Test switching key bindings to vi mode.
# This should leave the mode in the appropriate state (i.e., insert mode).
# Test switching key bindings to vi mode. This should leave the mode in the
# appropriate state (i.e., insert mode). These initial tests assume the
# default escape timeout of 500ms is in effect.
send "set -g fish_key_bindings fish_vi_key_bindings\r"
expect_prompt
send -h "echo fail\033"
send "echo fail: default escape timeout"
send "\033"
# Delay needed to allow fish to transition to vi "normal" mode.
sleep 0.510
send -h "ddiecho success\r"
expect_prompt -re {\r\nsuccess\r\n} {
puts "vi replace line success"
send "ddi"
send "echo success: default escape timeout\r"
expect_prompt -re {\r\nsuccess: default escape timeout\r\n} {
puts "vi replace line: default escape timeout"
} -nounmatched -re {\r\nfail} {
puts stderr "vi replace line fail"
puts stderr "vi replace line fail: default escape timeout"
} unmatched {
puts stderr "Couldn't find expected output 'success'"
puts stderr "couldn't find expected output: replace line, default escape timeout"
}
# Verify that a human can transpose words using \et (which is an emacs default
# binding but should be valid while in vi insert mode).
send "echo abc def\033"
# Fish should still be in vi "insert" mode after this delay.
send "echo abc def"
send "\033"
# Fish should still be in vi insert mode after this delay to simulate a slow
# typist.
sleep 0.400
send "t\r"
expect_prompt -re {\r\ndef abc\r\n} {
puts "vi transpose words success"
puts "vi transpose words: default escape timeout"
} unmatched {
puts stderr "vi transpose words fail"
puts stderr "vi transpose words fail: default escape timeout"
}
# Test replacing a single character.
send -h "echo TEXT\033"
send "echo TEXT"
send "\033"
# Delay needed to allow fish to transition to vi "normal" mode.
sleep 0.510
send -h "hhrAi\r"
send "hhrAi\r"
expect_prompt -re {\r\nTAXT\r\n} {
puts "vi mode replace success"
puts "vi mode replace: default escape timeout"
} -nounmatched -re {\r\nfail} {
puts stderr "vi mode replace fail"
puts stderr "vi mode replace fail: default escape timeout"
} unmatched {
puts stderr "Couldn't find expected output 'TAXT'"
puts stderr "couldn't find expected output 'TAXT': default escape timeout"
}
# Verify that changing the escape timeout has an effect. The vi key bindings
# should still be in effect.
send "set -g fish_escape_delay_ms 100\r"
expect_prompt
send "echo fail: shortened escape timeout"
send "\033"
sleep 0.110
send "ddi"
send "echo success: shortened escape timeout\r"
expect_prompt -re {\r\nsuccess: shortened escape timeout\r\n} {
puts "vi replace line: shortened escape timeout"
} -nounmatched -re {\r\nfail} {
puts stderr "vi replace line fail: shortened escape timeout"
} unmatched {
puts stderr "couldn't find expected output: replace_line, shortened escape timeout"
}
# Verify that we don't switch to vi normal mode if we don't wait long enough
# after sending escape. The vi key bindings should still be in effect.
send "echo fail: no normal mode"
send "\033"
sleep 0.050
send "ddi"
send "inserted\r"
expect_prompt -re {\r\nfail: no normal modediinserted\r\n} {
puts "vi normal mode: shortened escape timeout"
} -nounmatched -re {\r\nfail} {
puts stderr "vi normal mode fail: shortened escape timeout"
} unmatched {
puts stderr "couldn't find expected output: no normal mode"
}
# Switch back to regular (emacs mode) key bindings.
send -h "set -g fish_key_bindings fish_default_key_bindings\r"
send "set -g fish_key_bindings fish_default_key_bindings\r"
expect_prompt
send "echo success\r"
expect_prompt -re {\r\nsuccess\r\n} {
puts "emacs success"
# Verify the emacs transpose word (\et) behavior using various delays,
# including none, after the escape character.
# Start by testing with no delay. This should transpose the words.
send "echo abc def"
send "\033t\r"
expect_prompt -re {\r\ndef abc\r\n} {
puts "emacs transpose words: no escape delay"
} unmatched {
puts stderr "Couldn't find expected output 'success'"
} timeout {
set msg ""
append msg "Timeout after setting fish_key_bindings to fish_default_key_bindings\n" \
"\$fish_bind_mode is most likely still set to 'insert'"
abort $msg
puts stderr "emacs transpose words fail: no escape delay"
}
# Now test with a delay > 0 and < the escape timeout. This should transpose
# the words.
send "set -g fish_escape_delay_ms 100\r"
expect_prompt
send "echo ghi jkl"
send "\033"
sleep 0.050
send "t\r"
expect_prompt -re {\r\njkl ghi\r\n} {
puts "emacs transpose words: short escape delay"
} unmatched {
puts stderr "emacs transpose words fail: short escape delay"
}
# Now test with a delay > the escape timeout. The transposition should not
# occur and the "t" should become part of the text that is echoed.
send "echo mno pqr"
send "\033"
sleep 0.110
send "t\r"
expect_prompt -re {\r\nmno pqrt\r\n} {
puts "emacs transpose words: long escape delay"
} unmatched {
puts stderr "emacs transpose words fail: long escape delay"
}

View file

@ -1,4 +1,8 @@
vi replace line success
vi transpose words success
vi mode replace success
emacs success
vi replace line: default escape timeout
vi transpose words: default escape timeout
vi mode replace: default escape timeout
vi replace line: shortened escape timeout
vi normal mode: shortened escape timeout
emacs transpose words: no escape delay
emacs transpose words: short escape delay
emacs transpose words: long escape delay