From e7c9f6d47e446fd3fe237e9243929279de203588 Mon Sep 17 00:00:00 2001 From: Johannes Altmanninger Date: Fri, 18 Apr 2025 20:37:52 +0200 Subject: [PATCH] Move terminal query state data structure into the parser Whenever config.fish runs (interactive) builtin read, we push and pop a top-level, before the main shell's reader. The terminal state outlives all readers, so its scope should reflect that to avoid redundant initialization. Move it into the parser. This is also used by a following commit that wants to access the query state from a builtin. This should work even if no reader is active. Note that Mutex doesn't really make sense here - the next commit will fix that. --- src/input.rs | 2 +- src/parser.rs | 7 +++++-- src/reader.rs | 34 +++++++++++++--------------------- 3 files changed, 19 insertions(+), 24 deletions(-) diff --git a/src/input.rs b/src/input.rs index 5a826f524..c2715c755 100644 --- a/src/input.rs +++ b/src/input.rs @@ -451,7 +451,7 @@ fn paste_commit(&mut self) { } fn blocking_wait(&self) -> MutexGuard> { - self.data.blocking_wait() + Reader::blocking_wait(self) } fn on_mouse_left_click(&mut self, position: ViewportPosition) { diff --git a/src/parser.rs b/src/parser.rs index 63930f7a3..10c6228c9 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -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; +use crate::input_common::{terminal_protocols_disable_ifn, BlockingWait, Queried}; use crate::io::IoChain; use crate::job_group::MaybeJobId; use crate::operation_context::{OperationContext, EXPANSION_LIMIT_DEFAULT}; @@ -44,7 +44,7 @@ use std::rc::Rc; #[cfg(target_has_atomic = "64")] use std::sync::atomic::AtomicU64; -use std::sync::Arc; +use std::sync::{Arc, Mutex}; pub enum BlockData { Function { @@ -439,6 +439,8 @@ pub struct Parser { /// Global event blocks. pub global_event_blocks: AtomicU64, + + pub blocking_wait: Mutex>, } impl Parser { @@ -456,6 +458,7 @@ pub fn new(variables: Rc, cancel_behavior: CancelBehavior) -> Parser { cancel_behavior, profile_items: RefCell::default(), global_event_blocks: AtomicU64::new(0), + blocking_wait: Mutex::new(Some(BlockingWait::Startup(Queried::NotYet))), }; match open_dir(CStr::from_bytes_with_nul(b".\0").unwrap(), BEST_O_SEARCH) { diff --git a/src/reader.rs b/src/reader.rs index 6fcb97bd0..a4c048e80 100644 --- a/src/reader.rs +++ b/src/reader.rs @@ -83,7 +83,6 @@ use crate::input_common::BlockingWait; use crate::input_common::CursorPositionWait; use crate::input_common::ImplicitEvent; -use crate::input_common::InputEventQueuer; use crate::input_common::Queried; use crate::input_common::IN_DVTM; use crate::input_common::IN_MIDNIGHT_COMMANDER; @@ -543,8 +542,6 @@ pub struct ReaderData { /// The representation of the current screen contents. screen: Screen, - pub blocking_wait: Rc>>, - /// Data associated with input events. /// This is made public so that InputEventQueuer can be implemented on us. pub input_data: InputData, @@ -1179,10 +1176,6 @@ fn reader_received_sighup() -> bool { impl ReaderData { fn new(history: Arc, conf: ReaderConfig) -> Pin> { - let blocking_wait = reader_current_data().map_or_else( - || Rc::new(Mutex::new(Some(BlockingWait::Startup(Queried::NotYet)))), - |parent| parent.blocking_wait.clone(), - ); let input_data = InputData::new(conf.inputfd); Pin::new(Box::new(Self { canary: Rc::new(()), @@ -1200,7 +1193,6 @@ fn new(history: Arc, conf: ReaderConfig) -> Pin> { last_flash: Default::default(), flash_autosuggestion: false, screen: Screen::new(), - blocking_wait, input_data, queued_repaint: false, history, @@ -1227,10 +1219,6 @@ fn new(history: Arc, conf: ReaderConfig) -> Pin> { })) } - pub(crate) fn blocking_wait(&self) -> MutexGuard> { - self.blocking_wait.lock().unwrap() - } - // We repaint our prompt if fstat reports the tty as having changed. // But don't react to tty changes that we initiated, because of commands or // on-variable events (e.g. for fish_bind_mode). See #3481. @@ -1436,15 +1424,6 @@ fn update_buff_pos(&mut self, elt: EditableLineTag, mut new_pos: Option) true } - 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)); - out.write_command(QueryCursorPosition); - drop(wait_guard); - self.save_screen_state(); - } - pub fn mouse_left_click(&mut self, cursor: ViewportPosition, click_position: ViewportPosition) { FLOG!( reader, @@ -1518,6 +1497,19 @@ pub fn combine_command_and_autosuggestion( } impl<'a> Reader<'a> { + pub(crate) fn blocking_wait(&self) -> MutexGuard> { + self.parser.blocking_wait.lock().unwrap() + } + + 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)); + out.write_command(QueryCursorPosition); + drop(wait_guard); + self.save_screen_state(); + } + /// Return true if the command line has changed and repainting is needed. If `colors` is not /// null, then also return true if the colors have changed. fn is_repaint_needed(&self, mcolors: Option<&[HighlightSpec]>) -> bool {