mirror of
https://github.com/fish-shell/fish-shell
synced 2024-12-29 06:13:20 +00:00
added support for fish_sequence_key_delay_ms to set how long to wait between sequence key presses
This commit is contained in:
parent
724b44907e
commit
8a8c7abb0f
5 changed files with 56 additions and 12 deletions
|
@ -317,6 +317,7 @@ static std::unique_ptr<const var_dispatch_table_t> create_dispatch_table() {
|
|||
var_dispatch_table->add(L"fish_term256", handle_fish_term_change);
|
||||
var_dispatch_table->add(L"fish_term24bit", handle_fish_term_change);
|
||||
var_dispatch_table->add(L"fish_escape_delay_ms", update_wait_on_escape_ms);
|
||||
var_dispatch_table->add(L"fish_sequence_key_delay_ms", update_wait_on_sequence_key_ms);
|
||||
var_dispatch_table->add(L"fish_emoji_width", guess_emoji_width);
|
||||
var_dispatch_table->add(L"fish_ambiguous_width", handle_change_ambiguous_width);
|
||||
var_dispatch_table->add(L"LINES", handle_term_size_change);
|
||||
|
|
|
@ -237,7 +237,7 @@ static void process_input(bool continuous_mode, bool verbose) {
|
|||
if (reader_test_and_clear_interrupted()) {
|
||||
evt = char_event_t{shell_modes.c_cc[VINTR]};
|
||||
} else {
|
||||
evt = queue.readch_timed();
|
||||
evt = queue.readch_timed_esc();
|
||||
}
|
||||
if (!evt || !evt->is_char()) {
|
||||
output_bind_command(bind_chars);
|
||||
|
|
|
@ -465,19 +465,24 @@ class event_queue_peeker_t {
|
|||
|
||||
/// Check if the next event is the given character. This advances the index on success only.
|
||||
/// If \p timed is set, then return false if this (or any other) character had a timeout.
|
||||
bool next_is_char(wchar_t c, bool timed = false) {
|
||||
bool next_is_char(wchar_t c, bool escaped = false) {
|
||||
assert(idx_ <= peeked_.size() && "Index must not be larger than dequeued event count");
|
||||
// See if we had a timeout already.
|
||||
if (timed && had_timeout_) {
|
||||
if (escaped && had_timeout_) {
|
||||
return false;
|
||||
}
|
||||
// Grab a new event if we have exhausted what we have already peeked.
|
||||
// Use either readch or readch_timed, per our param.
|
||||
if (idx_ == peeked_.size()) {
|
||||
char_event_t newevt{L'\0'};
|
||||
if (!timed) {
|
||||
newevt = event_queue_.readch();
|
||||
} else if (auto mevt = event_queue_.readch_timed()) {
|
||||
if (!escaped) {
|
||||
if (auto mevt = event_queue_.readch_timed_sequence_key()) {
|
||||
newevt = mevt.acquire();
|
||||
} else {
|
||||
had_timeout_ = true;
|
||||
return false;
|
||||
}
|
||||
} else if (auto mevt = event_queue_.readch_timed_esc()) {
|
||||
newevt = mevt.acquire();
|
||||
} else {
|
||||
had_timeout_ = true;
|
||||
|
@ -542,7 +547,7 @@ static bool have_mouse_tracking_csi(event_queue_peeker_t *peeker) {
|
|||
// Maximum length of any CSI is NPAR (which is nominally 16), although this does not account for
|
||||
// user input intermixed with pseudo input generated by the tty emulator.
|
||||
// Check for the CSI first.
|
||||
if (!peeker->next_is_char(L'\x1b') || !peeker->next_is_char(L'[', true /* timed */)) {
|
||||
if (!peeker->next_is_char(L'\x1b') || !peeker->next_is_char(L'[', true /* escaped */)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -593,8 +598,8 @@ static bool try_peek_sequence(event_queue_peeker_t *peeker, const wcstring &str)
|
|||
for (wchar_t c : str) {
|
||||
// If we just read an escape, we need to add a timeout for the next char,
|
||||
// to distinguish between the actual escape key and an "alt"-modifier.
|
||||
bool timed = prev == L'\x1B';
|
||||
if (!peeker->next_is_char(c, timed)) {
|
||||
bool escaped = prev == L'\x1B';
|
||||
if (!peeker->next_is_char(c, escaped)) {
|
||||
return false;
|
||||
}
|
||||
prev = c;
|
||||
|
|
|
@ -34,6 +34,9 @@
|
|||
#define WAIT_ON_ESCAPE_DEFAULT 30
|
||||
static int wait_on_escape_ms = WAIT_ON_ESCAPE_DEFAULT;
|
||||
|
||||
#define WAIT_ON_SEQUENCE_KEY_INFINITE (-1)
|
||||
static int wait_on_sequence_key_ms = WAIT_ON_SEQUENCE_KEY_INFINITE;
|
||||
|
||||
input_event_queue_t::input_event_queue_t(int in) : in_(in) {}
|
||||
|
||||
/// Internal function used by readch to read one byte.
|
||||
|
@ -138,6 +141,26 @@ void update_wait_on_escape_ms(const environment_t& vars) {
|
|||
}
|
||||
}
|
||||
|
||||
// Update the wait_on_sequence_key_ms value in response to the fish_sequence_key_delay_ms user variable being
|
||||
// set.
|
||||
void update_wait_on_sequence_key_ms(const environment_t& vars) {
|
||||
auto sequence_key_time_ms = vars.get(L"fish_sequence_key_delay_ms");
|
||||
if (sequence_key_time_ms.missing_or_empty()) {
|
||||
wait_on_sequence_key_ms = WAIT_ON_SEQUENCE_KEY_INFINITE;
|
||||
return;
|
||||
}
|
||||
|
||||
long tmp = fish_wcstol(sequence_key_time_ms->as_string().c_str());
|
||||
if (errno || tmp < 10 || tmp >= 5000) {
|
||||
std::fwprintf(stderr,
|
||||
L"ignoring fish_sequence_key_delay_ms: value '%ls' "
|
||||
L"is not an integer or is < 10 or >= 5000 ms\n",
|
||||
sequence_key_time_ms->as_string().c_str());
|
||||
} else {
|
||||
wait_on_sequence_key_ms = static_cast<int>(tmp);
|
||||
}
|
||||
}
|
||||
|
||||
maybe_t<char_event_t> input_event_queue_t::try_pop() {
|
||||
if (queue_.empty()) {
|
||||
return none();
|
||||
|
@ -216,7 +239,18 @@ char_event_t input_event_queue_t::readch() {
|
|||
}
|
||||
}
|
||||
|
||||
maybe_t<char_event_t> input_event_queue_t::readch_timed() {
|
||||
maybe_t<char_event_t> input_event_queue_t::readch_timed_esc() {
|
||||
return readch_timed(wait_on_escape_ms);
|
||||
}
|
||||
|
||||
maybe_t<char_event_t> input_event_queue_t::readch_timed_sequence_key() {
|
||||
if (wait_on_sequence_key_ms == WAIT_ON_SEQUENCE_KEY_INFINITE) {
|
||||
return readch();
|
||||
}
|
||||
return readch_timed(wait_on_sequence_key_ms);
|
||||
}
|
||||
|
||||
maybe_t<char_event_t> input_event_queue_t::readch_timed(const int wait_time_ms) {
|
||||
if (auto evt = try_pop()) {
|
||||
return evt;
|
||||
}
|
||||
|
@ -229,7 +263,7 @@ maybe_t<char_event_t> input_event_queue_t::readch_timed() {
|
|||
// pselect expects timeouts in nanoseconds.
|
||||
const uint64_t nsec_per_msec = 1000 * 1000;
|
||||
const uint64_t nsec_per_sec = nsec_per_msec * 1000;
|
||||
const uint64_t wait_nsec = wait_on_escape_ms * nsec_per_msec;
|
||||
const uint64_t wait_nsec = wait_time_ms * nsec_per_msec;
|
||||
struct timespec timeout;
|
||||
timeout.tv_sec = (wait_nsec) / nsec_per_sec;
|
||||
timeout.tv_nsec = (wait_nsec) % nsec_per_sec;
|
||||
|
|
|
@ -188,6 +188,7 @@ class char_event_t {
|
|||
/// Adjust the escape timeout.
|
||||
class environment_t;
|
||||
void update_wait_on_escape_ms(const environment_t &vars);
|
||||
void update_wait_on_sequence_key_ms(const environment_t& vars);
|
||||
|
||||
/// A class which knows how to produce a stream of input events.
|
||||
/// This is a base class; you may subclass it for its override points.
|
||||
|
@ -204,7 +205,10 @@ class input_event_queue_t {
|
|||
/// Like readch(), except it will wait at most WAIT_ON_ESCAPE milliseconds for a
|
||||
/// character to be available for reading.
|
||||
/// \return none on timeout, the event on success.
|
||||
maybe_t<char_event_t> readch_timed();
|
||||
maybe_t<char_event_t> readch_timed(const int wait_time_ms);
|
||||
|
||||
maybe_t<char_event_t> readch_timed_esc();
|
||||
maybe_t<char_event_t> readch_timed_sequence_key();
|
||||
|
||||
/// Enqueue a character or a readline function to the queue of unread characters that
|
||||
/// readch will return before actually reading from fd 0.
|
||||
|
|
Loading…
Reference in a new issue