mirror of
https://github.com/fish-shell/fish-shell
synced 2024-12-27 21:33:09 +00:00
* added support for fish_sequence_key_delay_ms to set how long to wait between sequence key presses * fixed cargo fmt
This commit is contained in:
parent
b54faf9469
commit
01db48a712
6 changed files with 86 additions and 12 deletions
|
@ -61,6 +61,10 @@ static VAR_DISPATCH_TABLE: once_cell::sync::Lazy<VarDispatchTable> =
|
|||
table.add_anon(L!("fish_term256"), handle_fish_term_change);
|
||||
table.add_anon(L!("fish_term24bit"), handle_fish_term_change);
|
||||
table.add_anon(L!("fish_escape_delay_ms"), update_wait_on_escape_ms);
|
||||
table.add_anon(
|
||||
L!("fish_sequence_key_delay_ms"),
|
||||
update_wait_on_sequence_key_ms,
|
||||
);
|
||||
table.add_anon(L!("fish_emoji_width"), guess_emoji_width);
|
||||
table.add_anon(L!("fish_ambiguous_width"), handle_change_ambiguous_width);
|
||||
table.add_anon(L!("LINES"), handle_term_size_change);
|
||||
|
@ -105,6 +109,11 @@ fn update_wait_on_escape_ms(vars: &EnvStack) {
|
|||
let var = crate::env::environment::env_var_to_ffi(fish_escape_delay_ms);
|
||||
crate::ffi::update_wait_on_escape_ms_ffi(var);
|
||||
}
|
||||
fn update_wait_on_sequence_key_ms(vars: &EnvStack) {
|
||||
let fish_sequence_key_delay_ms = vars.get_unless_empty(L!("fish_sequence_key_delay_ms"));
|
||||
let var = crate::env::environment::env_var_to_ffi(fish_sequence_key_delay_ms);
|
||||
crate::ffi::update_wait_on_sequence_key_ms_ffi(var);
|
||||
}
|
||||
|
||||
impl VarDispatchTable {
|
||||
/// Add a callback for the variable `name`. We must not already be observing this variable.
|
||||
|
@ -366,6 +375,7 @@ fn run_inits(vars: &EnvStack) {
|
|||
init_curses(vars);
|
||||
guess_emoji_width(vars);
|
||||
update_wait_on_escape_ms(vars);
|
||||
update_wait_on_sequence_key_ms(vars);
|
||||
handle_read_limit_change(vars);
|
||||
handle_fish_use_posix_spawn_change(vars);
|
||||
handle_fish_trace(vars);
|
||||
|
|
|
@ -147,6 +147,7 @@ include_cpp! {
|
|||
generate!("complete_invalidate_path")
|
||||
generate!("complete_add_wrapper")
|
||||
generate!("update_wait_on_escape_ms_ffi")
|
||||
generate!("update_wait_on_sequence_key_ms_ffi")
|
||||
generate!("autoload_t")
|
||||
generate!("make_autoload_ffi")
|
||||
generate!("perform_autoload_ffi")
|
||||
|
|
|
@ -240,7 +240,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);
|
||||
|
|
|
@ -468,19 +468,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;
|
||||
|
@ -545,7 +550,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;
|
||||
}
|
||||
|
||||
|
@ -596,8 +601,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;
|
||||
|
|
|
@ -35,6 +35,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.
|
||||
|
@ -157,6 +160,44 @@ void update_wait_on_escape_ms_ffi(std::unique_ptr<env_var_t> fish_escape_delay_m
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// 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_unless_empty(L"fish_sequence_key_delay_ms");
|
||||
if (!sequence_key_time_ms) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
void update_wait_on_sequence_key_ms_ffi(std::unique_ptr<env_var_t> fish_sequence_key_delay_ms) {
|
||||
if (!fish_sequence_key_delay_ms) {
|
||||
wait_on_sequence_key_ms = WAIT_ON_SEQUENCE_KEY_INFINITE;
|
||||
return;
|
||||
}
|
||||
|
||||
long tmp = fish_wcstol(fish_sequence_key_delay_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",
|
||||
fish_sequence_key_delay_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();
|
||||
|
@ -235,7 +276,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;
|
||||
}
|
||||
|
@ -248,7 +300,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;
|
||||
|
|
|
@ -189,6 +189,9 @@ class environment_t;
|
|||
void update_wait_on_escape_ms(const environment_t &vars);
|
||||
void update_wait_on_escape_ms_ffi(std::unique_ptr<env_var_t> fish_escape_delay_ms);
|
||||
|
||||
void update_wait_on_sequence_key_ms(const environment_t &vars);
|
||||
void update_wait_on_sequence_key_ms_ffi(std::unique_ptr<env_var_t> fish_sequence_key_delay_ms);
|
||||
|
||||
/// 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.
|
||||
class input_event_queue_t {
|
||||
|
@ -204,7 +207,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