mirror of
https://github.com/fish-shell/fish-shell.git
synced 2025-01-19 16:02:44 +08:00
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:
parent
6969cfab3d
commit
4b9fece9f4
|
@ -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)
|
static void react_to_variable_change(const wcstring &key)
|
||||||
{
|
{
|
||||||
if (var_is_locale(key))
|
if (var_is_locale(key))
|
||||||
|
@ -319,6 +319,10 @@ static void react_to_variable_change(const wcstring &key)
|
||||||
{
|
{
|
||||||
reader_react_to_color_change();
|
reader_react_to_color_change();
|
||||||
}
|
}
|
||||||
|
else if (key == L"fish_escape_delay_ms")
|
||||||
|
{
|
||||||
|
update_wait_on_escape_ms();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -33,9 +33,11 @@ Implementation file for the low level input library
|
||||||
reading after \\x1b is read before assuming that escape key was
|
reading after \\x1b is read before assuming that escape key was
|
||||||
pressed, and not an escape sequence.
|
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 */
|
/** Characters that have been read and returned by the sequence matching code */
|
||||||
static std::deque<wint_t> lookahead_list;
|
static std::deque<wint_t> lookahead_list;
|
||||||
|
@ -79,6 +81,7 @@ static int (*interrupt_handler)();
|
||||||
void input_common_init(int (*ih)())
|
void input_common_init(int (*ih)())
|
||||||
{
|
{
|
||||||
interrupt_handler = ih;
|
interrupt_handler = ih;
|
||||||
|
update_wait_on_escape_ms();
|
||||||
}
|
}
|
||||||
|
|
||||||
void input_common_destroy()
|
void input_common_destroy()
|
||||||
|
@ -214,36 +217,48 @@ static wint_t readb()
|
||||||
return arr[0];
|
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)
|
wchar_t input_common_readch(int timed)
|
||||||
{
|
{
|
||||||
if (! has_lookahead())
|
if (! has_lookahead())
|
||||||
{
|
{
|
||||||
if (timed)
|
if (timed)
|
||||||
{
|
{
|
||||||
int count;
|
|
||||||
fd_set fds;
|
fd_set fds;
|
||||||
struct timeval tm=
|
|
||||||
{
|
|
||||||
0,
|
|
||||||
1000 * WAIT_ON_ESCAPE
|
|
||||||
}
|
|
||||||
;
|
|
||||||
|
|
||||||
FD_ZERO(&fds);
|
FD_ZERO(&fds);
|
||||||
FD_SET(0, &fds);
|
FD_SET(0, &fds);
|
||||||
count = select(1, &fds, 0, 0, &tm);
|
struct timeval tm = {wait_on_escape_ms / 1000,
|
||||||
|
1000 * (wait_on_escape_ms % 1000)};
|
||||||
switch (count)
|
int count = select(1, &fds, 0, 0, &tm);
|
||||||
|
if (count <= 0)
|
||||||
{
|
{
|
||||||
case 0:
|
return WEOF;
|
||||||
return WEOF;
|
|
||||||
|
|
||||||
case -1:
|
|
||||||
return WEOF;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,6 +35,9 @@ void input_common_init(int (*ih)());
|
||||||
*/
|
*/
|
||||||
void input_common_destroy();
|
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
|
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
|
bytes have been read to convert them to a wchar_t. Conversion is
|
||||||
|
|
|
@ -2,59 +2,124 @@
|
||||||
spawn $fish
|
spawn $fish
|
||||||
expect_prompt
|
expect_prompt
|
||||||
|
|
||||||
# Test switching key bindings to vi mode.
|
# Test switching key bindings to vi mode. This should leave the mode in the
|
||||||
# This should leave the mode in the appropriate state (i.e., insert mode).
|
# 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"
|
send "set -g fish_key_bindings fish_vi_key_bindings\r"
|
||||||
expect_prompt
|
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.
|
# Delay needed to allow fish to transition to vi "normal" mode.
|
||||||
sleep 0.510
|
sleep 0.510
|
||||||
send -h "ddiecho success\r"
|
send "ddi"
|
||||||
expect_prompt -re {\r\nsuccess\r\n} {
|
send "echo success: default escape timeout\r"
|
||||||
puts "vi replace line success"
|
expect_prompt -re {\r\nsuccess: default escape timeout\r\n} {
|
||||||
|
puts "vi replace line: default escape timeout"
|
||||||
} -nounmatched -re {\r\nfail} {
|
} -nounmatched -re {\r\nfail} {
|
||||||
puts stderr "vi replace line fail"
|
puts stderr "vi replace line fail: default escape timeout"
|
||||||
} unmatched {
|
} 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
|
# Verify that a human can transpose words using \et (which is an emacs default
|
||||||
# binding but should be valid while in vi insert mode).
|
# binding but should be valid while in vi insert mode).
|
||||||
send "echo abc def\033"
|
send "echo abc def"
|
||||||
# Fish should still be in vi "insert" mode after this delay.
|
send "\033"
|
||||||
|
# Fish should still be in vi insert mode after this delay to simulate a slow
|
||||||
|
# typist.
|
||||||
sleep 0.400
|
sleep 0.400
|
||||||
send "t\r"
|
send "t\r"
|
||||||
expect_prompt -re {\r\ndef abc\r\n} {
|
expect_prompt -re {\r\ndef abc\r\n} {
|
||||||
puts "vi transpose words success"
|
puts "vi transpose words: default escape timeout"
|
||||||
} unmatched {
|
} unmatched {
|
||||||
puts stderr "vi transpose words fail"
|
puts stderr "vi transpose words fail: default escape timeout"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Test replacing a single character.
|
# 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.
|
# Delay needed to allow fish to transition to vi "normal" mode.
|
||||||
sleep 0.510
|
sleep 0.510
|
||||||
send -h "hhrAi\r"
|
send "hhrAi\r"
|
||||||
expect_prompt -re {\r\nTAXT\r\n} {
|
expect_prompt -re {\r\nTAXT\r\n} {
|
||||||
puts "vi mode replace success"
|
puts "vi mode replace: default escape timeout"
|
||||||
} -nounmatched -re {\r\nfail} {
|
} -nounmatched -re {\r\nfail} {
|
||||||
puts stderr "vi mode replace fail"
|
puts stderr "vi mode replace fail: default escape timeout"
|
||||||
} unmatched {
|
} 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.
|
# 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
|
expect_prompt
|
||||||
send "echo success\r"
|
|
||||||
expect_prompt -re {\r\nsuccess\r\n} {
|
# Verify the emacs transpose word (\et) behavior using various delays,
|
||||||
puts "emacs success"
|
# 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 {
|
} unmatched {
|
||||||
puts stderr "Couldn't find expected output 'success'"
|
puts stderr "emacs transpose words fail: no escape delay"
|
||||||
} timeout {
|
}
|
||||||
set msg ""
|
|
||||||
append msg "Timeout after setting fish_key_bindings to fish_default_key_bindings\n" \
|
# Now test with a delay > 0 and < the escape timeout. This should transpose
|
||||||
"\$fish_bind_mode is most likely still set to 'insert'"
|
# the words.
|
||||||
abort $msg
|
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"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,8 @@
|
||||||
vi replace line success
|
vi replace line: default escape timeout
|
||||||
vi transpose words success
|
vi transpose words: default escape timeout
|
||||||
vi mode replace success
|
vi mode replace: default escape timeout
|
||||||
emacs success
|
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
|
||||||
|
|
Loading…
Reference in New Issue
Block a user