mirror of
https://github.com/fish-shell/fish-shell.git
synced 2026-05-31 20:31:19 -03:00
Rename terminal-query-state data structure
While at it, extract a function for initialization. This looks pretty ugly but it will get better with the next commit.
This commit is contained in:
@@ -7,7 +7,7 @@
|
||||
//!
|
||||
//! Type "exit" or "quit" to terminate the program.
|
||||
|
||||
use std::{ops::ControlFlow, os::unix::prelude::OsStrExt, sync::atomic::Ordering};
|
||||
use std::{cell::RefCell, ops::ControlFlow, os::unix::prelude::OsStrExt, sync::atomic::Ordering};
|
||||
|
||||
use libc::{STDIN_FILENO, TCSANOW, VEOF, VINTR};
|
||||
|
||||
@@ -19,20 +19,16 @@
|
||||
env::env_init,
|
||||
input_common::{
|
||||
terminal_protocol_hacks, terminal_protocols_enable_ifn, CharEvent, ImplicitEvent,
|
||||
InputEventQueue, InputEventQueuer, KeyEvent,
|
||||
InputEventQueue, InputEventQueuer, KeyEvent, Queried, TerminalQuery,
|
||||
},
|
||||
key::{char_to_symbol, Key, Modifiers},
|
||||
nix::isatty,
|
||||
panic::panic_handler,
|
||||
print_help::print_help,
|
||||
proc::set_interactive_session,
|
||||
reader::{check_exit_loop_maybe_warning, reader_init},
|
||||
reader::{check_exit_loop_maybe_warning, initial_query, reader_init},
|
||||
signal::signal_set_handlers,
|
||||
terminal::{
|
||||
Capability, Output,
|
||||
TerminalCommand::{QueryKittyKeyboardProgressiveEnhancements, QueryPrimaryDeviceAttribute},
|
||||
KITTY_KEYBOARD_SUPPORTED,
|
||||
},
|
||||
terminal::{Capability, KITTY_KEYBOARD_SUPPORTED},
|
||||
threads,
|
||||
topic_monitor::topic_monitor_init,
|
||||
wchar::prelude::*,
|
||||
@@ -155,11 +151,9 @@ fn setup_and_process_keys(
|
||||
// in fish-proper this is done once a command is run.
|
||||
unsafe { libc::tcsetattr(0, TCSANOW, &*shell_modes()) };
|
||||
terminal_protocol_hacks();
|
||||
|
||||
streams
|
||||
.out
|
||||
.write_command(QueryKittyKeyboardProgressiveEnhancements);
|
||||
streams.out.write_command(QueryPrimaryDeviceAttribute);
|
||||
let blocking_query: RefCell<Option<TerminalQuery>> =
|
||||
RefCell::new(Some(TerminalQuery::PrimaryDeviceAttribute(Queried::NotYet)));
|
||||
initial_query(&blocking_query, streams.out, None);
|
||||
|
||||
if continuous_mode {
|
||||
streams.err.append(L!("\n"));
|
||||
|
||||
10
src/input.rs
10
src/input.rs
@@ -7,8 +7,8 @@
|
||||
use crate::future::IsSomeAnd;
|
||||
use crate::global_safety::RelaxedAtomicBool;
|
||||
use crate::input_common::{
|
||||
BlockingWait, CharEvent, CharInputStyle, CursorPositionWait, ImplicitEvent, InputData,
|
||||
InputEventQueuer, ReadlineCmd, R_END_INPUT_FUNCTIONS,
|
||||
CharEvent, CharInputStyle, CursorPositionQuery, ImplicitEvent, InputData, InputEventQueuer,
|
||||
ReadlineCmd, TerminalQuery, R_END_INPUT_FUNCTIONS,
|
||||
};
|
||||
use crate::key::ViewportPosition;
|
||||
use crate::key::{self, canonicalize_raw_escapes, ctrl, Key, Modifiers};
|
||||
@@ -451,15 +451,15 @@ fn paste_commit(&mut self) {
|
||||
)));
|
||||
}
|
||||
|
||||
fn blocking_wait(&self) -> RefMut<'_, Option<BlockingWait>> {
|
||||
Reader::blocking_wait(self)
|
||||
fn blocking_query(&self) -> RefMut<'_, Option<TerminalQuery>> {
|
||||
Reader::blocking_query(self)
|
||||
}
|
||||
|
||||
fn on_mouse_left_click(&mut self, position: ViewportPosition) {
|
||||
FLOG!(reader, "Mouse left click", position);
|
||||
self.request_cursor_position(
|
||||
&mut Outputter::stdoutput().borrow_mut(),
|
||||
CursorPositionWait::MouseLeft(position),
|
||||
CursorPositionQuery::MouseLeft(position),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -755,7 +755,7 @@ pub fn function_set_status(&mut self, status: bool) {
|
||||
}
|
||||
|
||||
#[derive(Eq, PartialEq)]
|
||||
pub enum CursorPositionWait {
|
||||
pub enum CursorPositionQuery {
|
||||
MouseLeft(ViewportPosition),
|
||||
ScrollbackPush,
|
||||
}
|
||||
@@ -767,9 +767,9 @@ pub enum Queried {
|
||||
}
|
||||
|
||||
#[derive(Eq, PartialEq)]
|
||||
pub enum BlockingWait {
|
||||
Startup(Queried),
|
||||
CursorPosition(CursorPositionWait),
|
||||
pub enum TerminalQuery {
|
||||
PrimaryDeviceAttribute(Queried),
|
||||
CursorPositionReport(CursorPositionQuery),
|
||||
}
|
||||
|
||||
/// A trait which knows how to produce a stream of input events.
|
||||
@@ -777,7 +777,7 @@ pub enum BlockingWait {
|
||||
pub trait InputEventQueuer {
|
||||
/// Return the next event in the queue, or none if the queue is empty.
|
||||
fn try_pop(&mut self) -> Option<CharEvent> {
|
||||
if self.is_blocked() {
|
||||
if self.is_blocked_querying() {
|
||||
match self.get_input_data().queue.front()? {
|
||||
CharEvent::Key(_) | CharEvent::Readline(_) | CharEvent::Command(_) => {
|
||||
return None; // No code execution while blocked.
|
||||
@@ -909,7 +909,7 @@ fn try_readch(&mut self, blocking: bool) -> Option<CharEvent> {
|
||||
Some(seq.chars().skip(1).map(CharEvent::from_char)),
|
||||
)
|
||||
};
|
||||
if self.is_blocked() {
|
||||
if self.is_blocked_querying() {
|
||||
FLOG!(
|
||||
reader,
|
||||
"Still blocked on response from terminal, deferring key event",
|
||||
@@ -928,7 +928,7 @@ fn try_readch(&mut self, blocking: bool) -> Option<CharEvent> {
|
||||
reader,
|
||||
"Received interrupt key, giving up waiting for response from terminal"
|
||||
);
|
||||
let ok = unblock_input(self.blocking_wait());
|
||||
let ok = stop_query(self.blocking_query());
|
||||
assert!(ok);
|
||||
}
|
||||
continue;
|
||||
@@ -1131,15 +1131,15 @@ fn parse_csi(&mut self, buffer: &mut Vec<u8>) -> Option<KeyEvent> {
|
||||
if code != 0 || c != b'M' || modifiers.is_some() {
|
||||
return None;
|
||||
}
|
||||
let wait_guard = self.blocking_wait();
|
||||
let Some(wait) = &*wait_guard else {
|
||||
drop(wait_guard);
|
||||
let query = self.blocking_query();
|
||||
let Some(query) = &*query else {
|
||||
drop(query);
|
||||
self.on_mouse_left_click(position);
|
||||
return None;
|
||||
};
|
||||
match wait {
|
||||
BlockingWait::Startup(_) => {}
|
||||
BlockingWait::CursorPosition(_) => {
|
||||
match query {
|
||||
TerminalQuery::PrimaryDeviceAttribute(_) => {}
|
||||
TerminalQuery::CursorPositionReport(_) => {
|
||||
// TODO: re-queue it I guess.
|
||||
FLOG!(
|
||||
reader,
|
||||
@@ -1180,22 +1180,23 @@ fn parse_csi(&mut self, buffer: &mut Vec<u8>) -> Option<KeyEvent> {
|
||||
return invalid_sequence(buffer);
|
||||
};
|
||||
FLOG!(reader, "Received cursor position report y:", y, "x:", x);
|
||||
let wait_guard = self.blocking_wait();
|
||||
let Some(BlockingWait::CursorPosition(wait)) = &*wait_guard else {
|
||||
let query = self.blocking_query();
|
||||
use TerminalQuery::CursorPositionReport;
|
||||
let Some(CursorPositionReport(cursor_pos_query)) = &*query else {
|
||||
return None;
|
||||
};
|
||||
let continuation = match wait {
|
||||
CursorPositionWait::MouseLeft(click_position) => {
|
||||
let continuation = match cursor_pos_query {
|
||||
CursorPositionQuery::MouseLeft(click_position) => {
|
||||
ImplicitEvent::MouseLeftClickContinuation(
|
||||
ViewportPosition { x, y },
|
||||
*click_position,
|
||||
)
|
||||
}
|
||||
CursorPositionWait::ScrollbackPush => {
|
||||
CursorPositionQuery::ScrollbackPush => {
|
||||
ImplicitEvent::ScrollbackPushContinuation(y)
|
||||
}
|
||||
};
|
||||
drop(wait_guard);
|
||||
drop(query);
|
||||
self.push_front(CharEvent::Implicit(continuation));
|
||||
return None;
|
||||
}
|
||||
@@ -1628,9 +1629,9 @@ fn drop_leading_readline_events(&mut self) {
|
||||
}
|
||||
}
|
||||
|
||||
fn blocking_wait(&self) -> RefMut<'_, Option<BlockingWait>>;
|
||||
fn is_blocked(&self) -> bool {
|
||||
self.blocking_wait().is_some()
|
||||
fn blocking_query(&self) -> RefMut<'_, Option<TerminalQuery>>;
|
||||
fn is_blocked_querying(&self) -> bool {
|
||||
self.blocking_query().is_some()
|
||||
}
|
||||
|
||||
fn on_mouse_left_click(&mut self, _position: ViewportPosition) {}
|
||||
@@ -1646,7 +1647,7 @@ fn enqueue_interrupt_key(&mut self) {
|
||||
let vintr = shell_modes().c_cc[libc::VINTR];
|
||||
if vintr != 0 {
|
||||
let interrupt_evt = CharEvent::from_key(KeyEvent::from_single_byte(vintr));
|
||||
if unblock_input(self.blocking_wait()) {
|
||||
if stop_query(self.blocking_query()) {
|
||||
FLOG!(
|
||||
reader,
|
||||
"Received interrupt, giving up on waiting for terminal response"
|
||||
@@ -1750,12 +1751,8 @@ pub(crate) fn decode_input_byte(
|
||||
invalid(out_seq, || FLOG!(reader, "Illegal codepoint"))
|
||||
}
|
||||
|
||||
pub(crate) fn unblock_input(mut wait_guard: RefMut<'_, Option<BlockingWait>>) -> bool {
|
||||
if wait_guard.is_none() {
|
||||
return false;
|
||||
}
|
||||
*wait_guard = None;
|
||||
true
|
||||
pub(crate) fn stop_query(mut query: RefMut<'_, Option<TerminalQuery>>) -> bool {
|
||||
query.take().is_some()
|
||||
}
|
||||
|
||||
fn invalid_sequence(buffer: &[u8]) -> Option<KeyEvent> {
|
||||
@@ -1784,14 +1781,14 @@ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
/// A simple, concrete implementation of InputEventQueuer.
|
||||
pub struct InputEventQueue {
|
||||
data: InputData,
|
||||
blocking_wait: RefCell<Option<BlockingWait>>,
|
||||
blocking_query: RefCell<Option<TerminalQuery>>,
|
||||
}
|
||||
|
||||
impl InputEventQueue {
|
||||
pub fn new(in_fd: RawFd) -> Self {
|
||||
Self {
|
||||
data: InputData::new(in_fd),
|
||||
blocking_wait: RefCell::new(None),
|
||||
blocking_query: RefCell::new(None),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1810,8 +1807,8 @@ fn select_interrupted(&mut self) {
|
||||
self.enqueue_interrupt_key();
|
||||
}
|
||||
}
|
||||
fn blocking_wait(&self) -> RefMut<'_, Option<BlockingWait>> {
|
||||
self.blocking_wait.borrow_mut()
|
||||
fn blocking_query(&self) -> RefMut<'_, Option<TerminalQuery>> {
|
||||
self.blocking_query.borrow_mut()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
};
|
||||
use crate::fds::{open_dir, BEST_O_SEARCH};
|
||||
use crate::global_safety::RelaxedAtomicBool;
|
||||
use crate::input_common::{terminal_protocols_disable_ifn, BlockingWait, Queried};
|
||||
use crate::input_common::{terminal_protocols_disable_ifn, Queried, TerminalQuery};
|
||||
use crate::io::IoChain;
|
||||
use crate::job_group::MaybeJobId;
|
||||
use crate::operation_context::{OperationContext, EXPANSION_LIMIT_DEFAULT};
|
||||
@@ -440,7 +440,7 @@ pub struct Parser {
|
||||
/// Global event blocks.
|
||||
pub global_event_blocks: AtomicU64,
|
||||
|
||||
pub blocking_wait: RefCell<Option<BlockingWait>>,
|
||||
pub blocking_query: RefCell<Option<TerminalQuery>>,
|
||||
}
|
||||
|
||||
impl Parser {
|
||||
@@ -458,7 +458,9 @@ pub fn new(variables: Rc<EnvStack>, cancel_behavior: CancelBehavior) -> Parser {
|
||||
cancel_behavior,
|
||||
profile_items: RefCell::default(),
|
||||
global_event_blocks: AtomicU64::new(0),
|
||||
blocking_wait: RefCell::new(Some(BlockingWait::Startup(Queried::NotYet))),
|
||||
blocking_query: RefCell::new(Some(TerminalQuery::PrimaryDeviceAttribute(
|
||||
Queried::NotYet,
|
||||
))),
|
||||
};
|
||||
|
||||
match open_dir(CStr::from_bytes_with_nul(b".\0").unwrap(), BEST_O_SEARCH) {
|
||||
|
||||
110
src/reader.rs
110
src/reader.rs
@@ -23,6 +23,7 @@
|
||||
#[cfg(not(target_has_atomic = "64"))]
|
||||
use portable_atomic::AtomicU64;
|
||||
use std::borrow::Cow;
|
||||
use std::cell::RefCell;
|
||||
use std::cell::RefMut;
|
||||
use std::cell::UnsafeCell;
|
||||
use std::cmp;
|
||||
@@ -79,12 +80,12 @@
|
||||
SearchType,
|
||||
};
|
||||
use crate::input::init_input;
|
||||
use crate::input_common::stop_query;
|
||||
use crate::input_common::terminal_protocols_disable_ifn;
|
||||
use crate::input_common::unblock_input;
|
||||
use crate::input_common::BlockingWait;
|
||||
use crate::input_common::CursorPositionWait;
|
||||
use crate::input_common::CursorPositionQuery;
|
||||
use crate::input_common::ImplicitEvent;
|
||||
use crate::input_common::Queried;
|
||||
use crate::input_common::TerminalQuery;
|
||||
use crate::input_common::IN_DVTM;
|
||||
use crate::input_common::IN_MIDNIGHT_COMMANDER;
|
||||
use crate::input_common::{
|
||||
@@ -236,6 +237,31 @@ fn redirect_tty_after_sighup() {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn initial_query(
|
||||
blocking_query: &RefCell<Option<TerminalQuery>>,
|
||||
out: &mut impl Output,
|
||||
vars: Option<&dyn Environment>,
|
||||
) {
|
||||
if *blocking_query.borrow() != Some(TerminalQuery::PrimaryDeviceAttribute(Queried::NotYet)) {
|
||||
return;
|
||||
}
|
||||
*blocking_query.borrow_mut() = {
|
||||
let query = if is_dumb() || IN_MIDNIGHT_COMMANDER.load() || IN_DVTM.load() {
|
||||
None
|
||||
} else {
|
||||
// Query for kitty keyboard protocol support.
|
||||
out.write_command(QueryKittyKeyboardProgressiveEnhancements);
|
||||
out.write_command(QueryXtversion);
|
||||
if let Some(vars) = vars {
|
||||
query_capabilities_via_dcs(out.by_ref(), vars);
|
||||
}
|
||||
out.write_command(QueryPrimaryDeviceAttribute);
|
||||
Some(TerminalQuery::PrimaryDeviceAttribute(Queried::Yes))
|
||||
};
|
||||
query
|
||||
};
|
||||
}
|
||||
|
||||
/// The stack of current interactive reading contexts.
|
||||
fn reader_data_stack() -> &'static mut Vec<Pin<Box<ReaderData>>> {
|
||||
struct ReaderDataStack(UnsafeCell<Vec<Pin<Box<ReaderData>>>>);
|
||||
@@ -1498,16 +1524,16 @@ pub fn combine_command_and_autosuggestion(
|
||||
}
|
||||
|
||||
impl<'a> Reader<'a> {
|
||||
pub(crate) fn blocking_wait(&self) -> RefMut<'_, Option<BlockingWait>> {
|
||||
self.parser.blocking_wait.borrow_mut()
|
||||
pub(crate) fn blocking_query(&self) -> RefMut<'_, Option<TerminalQuery>> {
|
||||
self.parser.blocking_query.borrow_mut()
|
||||
}
|
||||
|
||||
pub fn request_cursor_position(&mut self, out: &mut Outputter, wait: CursorPositionWait) {
|
||||
let mut wait_guard = self.blocking_wait();
|
||||
assert!(wait_guard.is_none());
|
||||
*wait_guard = Some(BlockingWait::CursorPosition(wait));
|
||||
pub fn request_cursor_position(&mut self, out: &mut Outputter, q: CursorPositionQuery) {
|
||||
let mut query = self.blocking_query();
|
||||
assert!(query.is_none());
|
||||
*query = Some(TerminalQuery::CursorPositionReport(q));
|
||||
out.write_command(QueryCursorPosition);
|
||||
drop(wait_guard);
|
||||
drop(query);
|
||||
self.save_screen_state();
|
||||
}
|
||||
|
||||
@@ -2179,21 +2205,11 @@ fn readline(&mut self, nchars: Option<NonZeroUsize>) -> Option<WString> {
|
||||
}
|
||||
}
|
||||
|
||||
if *self.blocking_wait() == Some(BlockingWait::Startup(Queried::NotYet)) {
|
||||
if is_dumb() || IN_MIDNIGHT_COMMANDER.load() || IN_DVTM.load() {
|
||||
*self.blocking_wait() = None;
|
||||
} else {
|
||||
*self.blocking_wait() = Some(BlockingWait::Startup(Queried::Yes));
|
||||
let mut out = Outputter::stdoutput().borrow_mut();
|
||||
out.begin_buffering();
|
||||
// Query for kitty keyboard protocol support.
|
||||
out.write_command(QueryKittyKeyboardProgressiveEnhancements);
|
||||
out.write_command(QueryXtversion);
|
||||
query_capabilities_via_dcs(out.by_ref(), self.parser.vars());
|
||||
out.write_command(QueryPrimaryDeviceAttribute);
|
||||
out.end_buffering();
|
||||
}
|
||||
}
|
||||
initial_query(
|
||||
&self.parser.blocking_query,
|
||||
&mut BufferedOutputter::new(Outputter::stdoutput()),
|
||||
Some(self.parser.vars()),
|
||||
);
|
||||
|
||||
// HACK: Don't abandon line for the first prompt, because
|
||||
// if we're started with the terminal it might not have settled,
|
||||
@@ -2511,35 +2527,25 @@ fn handle_char_event(&mut self, injected_event: Option<CharEvent>) -> ControlFlo
|
||||
self.save_screen_state();
|
||||
}
|
||||
ImplicitEvent::PrimaryDeviceAttribute => {
|
||||
let wait_guard = self.blocking_wait();
|
||||
let Some(wait) = &*wait_guard else {
|
||||
let query = self.blocking_query();
|
||||
if !matches!(*query, Some(TerminalQuery::PrimaryDeviceAttribute(_))) {
|
||||
// Rogue reply.
|
||||
return ControlFlow::Continue(());
|
||||
};
|
||||
let BlockingWait::Startup(stage) = wait else {
|
||||
// Rogue reply.
|
||||
return ControlFlow::Continue(());
|
||||
};
|
||||
match stage {
|
||||
Queried::NotYet => panic!(),
|
||||
Queried::Yes => {
|
||||
if KITTY_KEYBOARD_SUPPORTED.load(Ordering::Relaxed)
|
||||
== Capability::Unknown as _
|
||||
{
|
||||
KITTY_KEYBOARD_SUPPORTED
|
||||
.store(Capability::NotSupported as _, Ordering::Release);
|
||||
}
|
||||
}
|
||||
}
|
||||
unblock_input(wait_guard);
|
||||
if KITTY_KEYBOARD_SUPPORTED.load(Ordering::Relaxed) == Capability::Unknown as _
|
||||
{
|
||||
KITTY_KEYBOARD_SUPPORTED
|
||||
.store(Capability::NotSupported as _, Ordering::Release);
|
||||
}
|
||||
stop_query(query);
|
||||
}
|
||||
ImplicitEvent::MouseLeftClickContinuation(cursor, click_position) => {
|
||||
self.mouse_left_click(cursor, click_position);
|
||||
unblock_input(self.blocking_wait());
|
||||
stop_query(self.blocking_query());
|
||||
}
|
||||
ImplicitEvent::ScrollbackPushContinuation(cursor_y) => {
|
||||
self.screen.push_to_scrollback(cursor_y);
|
||||
unblock_input(self.blocking_wait());
|
||||
stop_query(self.blocking_query());
|
||||
}
|
||||
},
|
||||
}
|
||||
@@ -3798,18 +3804,18 @@ fn handle_readline_command(&mut self, c: ReadlineCmd) {
|
||||
if !SCROLL_FORWARD_SUPPORTED.load() {
|
||||
return;
|
||||
}
|
||||
let wait_guard = self.blocking_wait();
|
||||
let Some(wait) = &*wait_guard else {
|
||||
drop(wait_guard);
|
||||
let query = self.blocking_query();
|
||||
let Some(query) = &*query else {
|
||||
drop(query);
|
||||
self.request_cursor_position(
|
||||
&mut Outputter::stdoutput().borrow_mut(),
|
||||
CursorPositionWait::ScrollbackPush,
|
||||
CursorPositionQuery::ScrollbackPush,
|
||||
);
|
||||
return;
|
||||
};
|
||||
match wait {
|
||||
BlockingWait::Startup(_) => panic!(),
|
||||
BlockingWait::CursorPosition(_) => {
|
||||
match query {
|
||||
TerminalQuery::PrimaryDeviceAttribute(_) => panic!(),
|
||||
TerminalQuery::CursorPositionReport(_) => {
|
||||
// TODO: re-queue it I guess.
|
||||
FLOG!(
|
||||
reader,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use crate::env::EnvStack;
|
||||
use crate::input::{EventQueuePeeker, InputMappingSet, KeyNameStyle, DEFAULT_BIND_MODE};
|
||||
use crate::input_common::{BlockingWait, CharEvent, InputData, InputEventQueuer, KeyEvent};
|
||||
use crate::input_common::{CharEvent, InputData, InputEventQueuer, KeyEvent, TerminalQuery};
|
||||
use crate::key::Key;
|
||||
use crate::wchar::prelude::*;
|
||||
use std::cell::{RefCell, RefMut};
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
struct TestInputEventQueuer {
|
||||
input_data: InputData,
|
||||
blocking_wait: RefCell<Option<BlockingWait>>,
|
||||
blocking_query: RefCell<Option<TerminalQuery>>,
|
||||
}
|
||||
|
||||
impl InputEventQueuer for TestInputEventQueuer {
|
||||
@@ -18,8 +18,8 @@ fn get_input_data(&self) -> &InputData {
|
||||
fn get_input_data_mut(&mut self) -> &mut InputData {
|
||||
&mut self.input_data
|
||||
}
|
||||
fn blocking_wait(&self) -> RefMut<'_, Option<BlockingWait>> {
|
||||
self.blocking_wait.borrow_mut()
|
||||
fn blocking_query(&self) -> RefMut<'_, Option<TerminalQuery>> {
|
||||
self.blocking_query.borrow_mut()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ fn test_input() {
|
||||
let vars = Rc::new(EnvStack::new());
|
||||
let mut input = TestInputEventQueuer {
|
||||
input_data: InputData::new(i32::MAX), // value doesn't matter since we don't read from it
|
||||
blocking_wait: RefCell::new(None),
|
||||
blocking_query: RefCell::new(None),
|
||||
};
|
||||
// Ensure sequences are order independent. Here we add two bindings where the first is a prefix
|
||||
// of the second, and then emit the second key list. The second binding should be invoked, not
|
||||
|
||||
Reference in New Issue
Block a user