mirror of
https://github.com/fish-shell/fish-shell.git
synced 2026-06-02 05:41:16 -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.
|
//! 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};
|
use libc::{STDIN_FILENO, TCSANOW, VEOF, VINTR};
|
||||||
|
|
||||||
@@ -19,20 +19,16 @@
|
|||||||
env::env_init,
|
env::env_init,
|
||||||
input_common::{
|
input_common::{
|
||||||
terminal_protocol_hacks, terminal_protocols_enable_ifn, CharEvent, ImplicitEvent,
|
terminal_protocol_hacks, terminal_protocols_enable_ifn, CharEvent, ImplicitEvent,
|
||||||
InputEventQueue, InputEventQueuer, KeyEvent,
|
InputEventQueue, InputEventQueuer, KeyEvent, Queried, TerminalQuery,
|
||||||
},
|
},
|
||||||
key::{char_to_symbol, Key, Modifiers},
|
key::{char_to_symbol, Key, Modifiers},
|
||||||
nix::isatty,
|
nix::isatty,
|
||||||
panic::panic_handler,
|
panic::panic_handler,
|
||||||
print_help::print_help,
|
print_help::print_help,
|
||||||
proc::set_interactive_session,
|
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,
|
signal::signal_set_handlers,
|
||||||
terminal::{
|
terminal::{Capability, KITTY_KEYBOARD_SUPPORTED},
|
||||||
Capability, Output,
|
|
||||||
TerminalCommand::{QueryKittyKeyboardProgressiveEnhancements, QueryPrimaryDeviceAttribute},
|
|
||||||
KITTY_KEYBOARD_SUPPORTED,
|
|
||||||
},
|
|
||||||
threads,
|
threads,
|
||||||
topic_monitor::topic_monitor_init,
|
topic_monitor::topic_monitor_init,
|
||||||
wchar::prelude::*,
|
wchar::prelude::*,
|
||||||
@@ -155,11 +151,9 @@ fn setup_and_process_keys(
|
|||||||
// in fish-proper this is done once a command is run.
|
// in fish-proper this is done once a command is run.
|
||||||
unsafe { libc::tcsetattr(0, TCSANOW, &*shell_modes()) };
|
unsafe { libc::tcsetattr(0, TCSANOW, &*shell_modes()) };
|
||||||
terminal_protocol_hacks();
|
terminal_protocol_hacks();
|
||||||
|
let blocking_query: RefCell<Option<TerminalQuery>> =
|
||||||
streams
|
RefCell::new(Some(TerminalQuery::PrimaryDeviceAttribute(Queried::NotYet)));
|
||||||
.out
|
initial_query(&blocking_query, streams.out, None);
|
||||||
.write_command(QueryKittyKeyboardProgressiveEnhancements);
|
|
||||||
streams.out.write_command(QueryPrimaryDeviceAttribute);
|
|
||||||
|
|
||||||
if continuous_mode {
|
if continuous_mode {
|
||||||
streams.err.append(L!("\n"));
|
streams.err.append(L!("\n"));
|
||||||
|
|||||||
10
src/input.rs
10
src/input.rs
@@ -7,8 +7,8 @@
|
|||||||
use crate::future::IsSomeAnd;
|
use crate::future::IsSomeAnd;
|
||||||
use crate::global_safety::RelaxedAtomicBool;
|
use crate::global_safety::RelaxedAtomicBool;
|
||||||
use crate::input_common::{
|
use crate::input_common::{
|
||||||
BlockingWait, CharEvent, CharInputStyle, CursorPositionWait, ImplicitEvent, InputData,
|
CharEvent, CharInputStyle, CursorPositionQuery, ImplicitEvent, InputData, InputEventQueuer,
|
||||||
InputEventQueuer, ReadlineCmd, R_END_INPUT_FUNCTIONS,
|
ReadlineCmd, TerminalQuery, R_END_INPUT_FUNCTIONS,
|
||||||
};
|
};
|
||||||
use crate::key::ViewportPosition;
|
use crate::key::ViewportPosition;
|
||||||
use crate::key::{self, canonicalize_raw_escapes, ctrl, Key, Modifiers};
|
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>> {
|
fn blocking_query(&self) -> RefMut<'_, Option<TerminalQuery>> {
|
||||||
Reader::blocking_wait(self)
|
Reader::blocking_query(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_mouse_left_click(&mut self, position: ViewportPosition) {
|
fn on_mouse_left_click(&mut self, position: ViewportPosition) {
|
||||||
FLOG!(reader, "Mouse left click", position);
|
FLOG!(reader, "Mouse left click", position);
|
||||||
self.request_cursor_position(
|
self.request_cursor_position(
|
||||||
&mut Outputter::stdoutput().borrow_mut(),
|
&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)]
|
#[derive(Eq, PartialEq)]
|
||||||
pub enum CursorPositionWait {
|
pub enum CursorPositionQuery {
|
||||||
MouseLeft(ViewportPosition),
|
MouseLeft(ViewportPosition),
|
||||||
ScrollbackPush,
|
ScrollbackPush,
|
||||||
}
|
}
|
||||||
@@ -767,9 +767,9 @@ pub enum Queried {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Eq, PartialEq)]
|
#[derive(Eq, PartialEq)]
|
||||||
pub enum BlockingWait {
|
pub enum TerminalQuery {
|
||||||
Startup(Queried),
|
PrimaryDeviceAttribute(Queried),
|
||||||
CursorPosition(CursorPositionWait),
|
CursorPositionReport(CursorPositionQuery),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A trait which knows how to produce a stream of input events.
|
/// A trait which knows how to produce a stream of input events.
|
||||||
@@ -777,7 +777,7 @@ pub enum BlockingWait {
|
|||||||
pub trait InputEventQueuer {
|
pub trait InputEventQueuer {
|
||||||
/// Return the next event in the queue, or none if the queue is empty.
|
/// Return the next event in the queue, or none if the queue is empty.
|
||||||
fn try_pop(&mut self) -> Option<CharEvent> {
|
fn try_pop(&mut self) -> Option<CharEvent> {
|
||||||
if self.is_blocked() {
|
if self.is_blocked_querying() {
|
||||||
match self.get_input_data().queue.front()? {
|
match self.get_input_data().queue.front()? {
|
||||||
CharEvent::Key(_) | CharEvent::Readline(_) | CharEvent::Command(_) => {
|
CharEvent::Key(_) | CharEvent::Readline(_) | CharEvent::Command(_) => {
|
||||||
return None; // No code execution while blocked.
|
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)),
|
Some(seq.chars().skip(1).map(CharEvent::from_char)),
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
if self.is_blocked() {
|
if self.is_blocked_querying() {
|
||||||
FLOG!(
|
FLOG!(
|
||||||
reader,
|
reader,
|
||||||
"Still blocked on response from terminal, deferring key event",
|
"Still blocked on response from terminal, deferring key event",
|
||||||
@@ -928,7 +928,7 @@ fn try_readch(&mut self, blocking: bool) -> Option<CharEvent> {
|
|||||||
reader,
|
reader,
|
||||||
"Received interrupt key, giving up waiting for response from terminal"
|
"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);
|
assert!(ok);
|
||||||
}
|
}
|
||||||
continue;
|
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() {
|
if code != 0 || c != b'M' || modifiers.is_some() {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
let wait_guard = self.blocking_wait();
|
let query = self.blocking_query();
|
||||||
let Some(wait) = &*wait_guard else {
|
let Some(query) = &*query else {
|
||||||
drop(wait_guard);
|
drop(query);
|
||||||
self.on_mouse_left_click(position);
|
self.on_mouse_left_click(position);
|
||||||
return None;
|
return None;
|
||||||
};
|
};
|
||||||
match wait {
|
match query {
|
||||||
BlockingWait::Startup(_) => {}
|
TerminalQuery::PrimaryDeviceAttribute(_) => {}
|
||||||
BlockingWait::CursorPosition(_) => {
|
TerminalQuery::CursorPositionReport(_) => {
|
||||||
// TODO: re-queue it I guess.
|
// TODO: re-queue it I guess.
|
||||||
FLOG!(
|
FLOG!(
|
||||||
reader,
|
reader,
|
||||||
@@ -1180,22 +1180,23 @@ fn parse_csi(&mut self, buffer: &mut Vec<u8>) -> Option<KeyEvent> {
|
|||||||
return invalid_sequence(buffer);
|
return invalid_sequence(buffer);
|
||||||
};
|
};
|
||||||
FLOG!(reader, "Received cursor position report y:", y, "x:", x);
|
FLOG!(reader, "Received cursor position report y:", y, "x:", x);
|
||||||
let wait_guard = self.blocking_wait();
|
let query = self.blocking_query();
|
||||||
let Some(BlockingWait::CursorPosition(wait)) = &*wait_guard else {
|
use TerminalQuery::CursorPositionReport;
|
||||||
|
let Some(CursorPositionReport(cursor_pos_query)) = &*query else {
|
||||||
return None;
|
return None;
|
||||||
};
|
};
|
||||||
let continuation = match wait {
|
let continuation = match cursor_pos_query {
|
||||||
CursorPositionWait::MouseLeft(click_position) => {
|
CursorPositionQuery::MouseLeft(click_position) => {
|
||||||
ImplicitEvent::MouseLeftClickContinuation(
|
ImplicitEvent::MouseLeftClickContinuation(
|
||||||
ViewportPosition { x, y },
|
ViewportPosition { x, y },
|
||||||
*click_position,
|
*click_position,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
CursorPositionWait::ScrollbackPush => {
|
CursorPositionQuery::ScrollbackPush => {
|
||||||
ImplicitEvent::ScrollbackPushContinuation(y)
|
ImplicitEvent::ScrollbackPushContinuation(y)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
drop(wait_guard);
|
drop(query);
|
||||||
self.push_front(CharEvent::Implicit(continuation));
|
self.push_front(CharEvent::Implicit(continuation));
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
@@ -1628,9 +1629,9 @@ fn drop_leading_readline_events(&mut self) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn blocking_wait(&self) -> RefMut<'_, Option<BlockingWait>>;
|
fn blocking_query(&self) -> RefMut<'_, Option<TerminalQuery>>;
|
||||||
fn is_blocked(&self) -> bool {
|
fn is_blocked_querying(&self) -> bool {
|
||||||
self.blocking_wait().is_some()
|
self.blocking_query().is_some()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_mouse_left_click(&mut self, _position: ViewportPosition) {}
|
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];
|
let vintr = shell_modes().c_cc[libc::VINTR];
|
||||||
if vintr != 0 {
|
if vintr != 0 {
|
||||||
let interrupt_evt = CharEvent::from_key(KeyEvent::from_single_byte(vintr));
|
let interrupt_evt = CharEvent::from_key(KeyEvent::from_single_byte(vintr));
|
||||||
if unblock_input(self.blocking_wait()) {
|
if stop_query(self.blocking_query()) {
|
||||||
FLOG!(
|
FLOG!(
|
||||||
reader,
|
reader,
|
||||||
"Received interrupt, giving up on waiting for terminal response"
|
"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"))
|
invalid(out_seq, || FLOG!(reader, "Illegal codepoint"))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn unblock_input(mut wait_guard: RefMut<'_, Option<BlockingWait>>) -> bool {
|
pub(crate) fn stop_query(mut query: RefMut<'_, Option<TerminalQuery>>) -> bool {
|
||||||
if wait_guard.is_none() {
|
query.take().is_some()
|
||||||
return false;
|
|
||||||
}
|
|
||||||
*wait_guard = None;
|
|
||||||
true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn invalid_sequence(buffer: &[u8]) -> Option<KeyEvent> {
|
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.
|
/// A simple, concrete implementation of InputEventQueuer.
|
||||||
pub struct InputEventQueue {
|
pub struct InputEventQueue {
|
||||||
data: InputData,
|
data: InputData,
|
||||||
blocking_wait: RefCell<Option<BlockingWait>>,
|
blocking_query: RefCell<Option<TerminalQuery>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl InputEventQueue {
|
impl InputEventQueue {
|
||||||
pub fn new(in_fd: RawFd) -> Self {
|
pub fn new(in_fd: RawFd) -> Self {
|
||||||
Self {
|
Self {
|
||||||
data: InputData::new(in_fd),
|
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();
|
self.enqueue_interrupt_key();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn blocking_wait(&self) -> RefMut<'_, Option<BlockingWait>> {
|
fn blocking_query(&self) -> RefMut<'_, Option<TerminalQuery>> {
|
||||||
self.blocking_wait.borrow_mut()
|
self.blocking_query.borrow_mut()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
};
|
};
|
||||||
use crate::fds::{open_dir, BEST_O_SEARCH};
|
use crate::fds::{open_dir, BEST_O_SEARCH};
|
||||||
use crate::global_safety::RelaxedAtomicBool;
|
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::io::IoChain;
|
||||||
use crate::job_group::MaybeJobId;
|
use crate::job_group::MaybeJobId;
|
||||||
use crate::operation_context::{OperationContext, EXPANSION_LIMIT_DEFAULT};
|
use crate::operation_context::{OperationContext, EXPANSION_LIMIT_DEFAULT};
|
||||||
@@ -440,7 +440,7 @@ pub struct Parser {
|
|||||||
/// Global event blocks.
|
/// Global event blocks.
|
||||||
pub global_event_blocks: AtomicU64,
|
pub global_event_blocks: AtomicU64,
|
||||||
|
|
||||||
pub blocking_wait: RefCell<Option<BlockingWait>>,
|
pub blocking_query: RefCell<Option<TerminalQuery>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parser {
|
impl Parser {
|
||||||
@@ -458,7 +458,9 @@ pub fn new(variables: Rc<EnvStack>, cancel_behavior: CancelBehavior) -> Parser {
|
|||||||
cancel_behavior,
|
cancel_behavior,
|
||||||
profile_items: RefCell::default(),
|
profile_items: RefCell::default(),
|
||||||
global_event_blocks: AtomicU64::new(0),
|
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) {
|
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"))]
|
#[cfg(not(target_has_atomic = "64"))]
|
||||||
use portable_atomic::AtomicU64;
|
use portable_atomic::AtomicU64;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
use std::cell::RefCell;
|
||||||
use std::cell::RefMut;
|
use std::cell::RefMut;
|
||||||
use std::cell::UnsafeCell;
|
use std::cell::UnsafeCell;
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
@@ -79,12 +80,12 @@
|
|||||||
SearchType,
|
SearchType,
|
||||||
};
|
};
|
||||||
use crate::input::init_input;
|
use crate::input::init_input;
|
||||||
|
use crate::input_common::stop_query;
|
||||||
use crate::input_common::terminal_protocols_disable_ifn;
|
use crate::input_common::terminal_protocols_disable_ifn;
|
||||||
use crate::input_common::unblock_input;
|
use crate::input_common::CursorPositionQuery;
|
||||||
use crate::input_common::BlockingWait;
|
|
||||||
use crate::input_common::CursorPositionWait;
|
|
||||||
use crate::input_common::ImplicitEvent;
|
use crate::input_common::ImplicitEvent;
|
||||||
use crate::input_common::Queried;
|
use crate::input_common::Queried;
|
||||||
|
use crate::input_common::TerminalQuery;
|
||||||
use crate::input_common::IN_DVTM;
|
use crate::input_common::IN_DVTM;
|
||||||
use crate::input_common::IN_MIDNIGHT_COMMANDER;
|
use crate::input_common::IN_MIDNIGHT_COMMANDER;
|
||||||
use crate::input_common::{
|
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.
|
/// The stack of current interactive reading contexts.
|
||||||
fn reader_data_stack() -> &'static mut Vec<Pin<Box<ReaderData>>> {
|
fn reader_data_stack() -> &'static mut Vec<Pin<Box<ReaderData>>> {
|
||||||
struct ReaderDataStack(UnsafeCell<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> {
|
impl<'a> Reader<'a> {
|
||||||
pub(crate) fn blocking_wait(&self) -> RefMut<'_, Option<BlockingWait>> {
|
pub(crate) fn blocking_query(&self) -> RefMut<'_, Option<TerminalQuery>> {
|
||||||
self.parser.blocking_wait.borrow_mut()
|
self.parser.blocking_query.borrow_mut()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn request_cursor_position(&mut self, out: &mut Outputter, wait: CursorPositionWait) {
|
pub fn request_cursor_position(&mut self, out: &mut Outputter, q: CursorPositionQuery) {
|
||||||
let mut wait_guard = self.blocking_wait();
|
let mut query = self.blocking_query();
|
||||||
assert!(wait_guard.is_none());
|
assert!(query.is_none());
|
||||||
*wait_guard = Some(BlockingWait::CursorPosition(wait));
|
*query = Some(TerminalQuery::CursorPositionReport(q));
|
||||||
out.write_command(QueryCursorPosition);
|
out.write_command(QueryCursorPosition);
|
||||||
drop(wait_guard);
|
drop(query);
|
||||||
self.save_screen_state();
|
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)) {
|
initial_query(
|
||||||
if is_dumb() || IN_MIDNIGHT_COMMANDER.load() || IN_DVTM.load() {
|
&self.parser.blocking_query,
|
||||||
*self.blocking_wait() = None;
|
&mut BufferedOutputter::new(Outputter::stdoutput()),
|
||||||
} else {
|
Some(self.parser.vars()),
|
||||||
*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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// HACK: Don't abandon line for the first prompt, because
|
// HACK: Don't abandon line for the first prompt, because
|
||||||
// if we're started with the terminal it might not have settled,
|
// 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();
|
self.save_screen_state();
|
||||||
}
|
}
|
||||||
ImplicitEvent::PrimaryDeviceAttribute => {
|
ImplicitEvent::PrimaryDeviceAttribute => {
|
||||||
let wait_guard = self.blocking_wait();
|
let query = self.blocking_query();
|
||||||
let Some(wait) = &*wait_guard else {
|
if !matches!(*query, Some(TerminalQuery::PrimaryDeviceAttribute(_))) {
|
||||||
// Rogue reply.
|
// Rogue reply.
|
||||||
return ControlFlow::Continue(());
|
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) => {
|
ImplicitEvent::MouseLeftClickContinuation(cursor, click_position) => {
|
||||||
self.mouse_left_click(cursor, click_position);
|
self.mouse_left_click(cursor, click_position);
|
||||||
unblock_input(self.blocking_wait());
|
stop_query(self.blocking_query());
|
||||||
}
|
}
|
||||||
ImplicitEvent::ScrollbackPushContinuation(cursor_y) => {
|
ImplicitEvent::ScrollbackPushContinuation(cursor_y) => {
|
||||||
self.screen.push_to_scrollback(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() {
|
if !SCROLL_FORWARD_SUPPORTED.load() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let wait_guard = self.blocking_wait();
|
let query = self.blocking_query();
|
||||||
let Some(wait) = &*wait_guard else {
|
let Some(query) = &*query else {
|
||||||
drop(wait_guard);
|
drop(query);
|
||||||
self.request_cursor_position(
|
self.request_cursor_position(
|
||||||
&mut Outputter::stdoutput().borrow_mut(),
|
&mut Outputter::stdoutput().borrow_mut(),
|
||||||
CursorPositionWait::ScrollbackPush,
|
CursorPositionQuery::ScrollbackPush,
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
match wait {
|
match query {
|
||||||
BlockingWait::Startup(_) => panic!(),
|
TerminalQuery::PrimaryDeviceAttribute(_) => panic!(),
|
||||||
BlockingWait::CursorPosition(_) => {
|
TerminalQuery::CursorPositionReport(_) => {
|
||||||
// TODO: re-queue it I guess.
|
// TODO: re-queue it I guess.
|
||||||
FLOG!(
|
FLOG!(
|
||||||
reader,
|
reader,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use crate::env::EnvStack;
|
use crate::env::EnvStack;
|
||||||
use crate::input::{EventQueuePeeker, InputMappingSet, KeyNameStyle, DEFAULT_BIND_MODE};
|
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::key::Key;
|
||||||
use crate::wchar::prelude::*;
|
use crate::wchar::prelude::*;
|
||||||
use std::cell::{RefCell, RefMut};
|
use std::cell::{RefCell, RefMut};
|
||||||
@@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
struct TestInputEventQueuer {
|
struct TestInputEventQueuer {
|
||||||
input_data: InputData,
|
input_data: InputData,
|
||||||
blocking_wait: RefCell<Option<BlockingWait>>,
|
blocking_query: RefCell<Option<TerminalQuery>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl InputEventQueuer for TestInputEventQueuer {
|
impl InputEventQueuer for TestInputEventQueuer {
|
||||||
@@ -18,8 +18,8 @@ fn get_input_data(&self) -> &InputData {
|
|||||||
fn get_input_data_mut(&mut self) -> &mut InputData {
|
fn get_input_data_mut(&mut self) -> &mut InputData {
|
||||||
&mut self.input_data
|
&mut self.input_data
|
||||||
}
|
}
|
||||||
fn blocking_wait(&self) -> RefMut<'_, Option<BlockingWait>> {
|
fn blocking_query(&self) -> RefMut<'_, Option<TerminalQuery>> {
|
||||||
self.blocking_wait.borrow_mut()
|
self.blocking_query.borrow_mut()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -28,7 +28,7 @@ fn test_input() {
|
|||||||
let vars = Rc::new(EnvStack::new());
|
let vars = Rc::new(EnvStack::new());
|
||||||
let mut input = TestInputEventQueuer {
|
let mut input = TestInputEventQueuer {
|
||||||
input_data: InputData::new(i32::MAX), // value doesn't matter since we don't read from it
|
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
|
// 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
|
// of the second, and then emit the second key list. The second binding should be invoked, not
|
||||||
|
|||||||
Reference in New Issue
Block a user