From ca9c5f4ceca93e4c426b758c3204f183825d9ef6 Mon Sep 17 00:00:00 2001 From: Johannes Altmanninger Date: Sun, 29 Dec 2024 19:31:15 +0100 Subject: [PATCH] Move some fake readline commands to a separate type --- src/input.rs | 26 ++++++++-------------- src/input_common.rs | 49 ++++++++++++++++++++-------------------- src/reader.rs | 54 +++++++++++++++++++++------------------------ 3 files changed, 59 insertions(+), 70 deletions(-) diff --git a/src/input.rs b/src/input.rs index fdca0f863..984d8c319 100644 --- a/src/input.rs +++ b/src/input.rs @@ -4,7 +4,8 @@ use crate::env::{Environment, CURSES_INITIALIZED}; use crate::event; use crate::flog::FLOG; use crate::input_common::{ - CharEvent, CharInputStyle, InputData, InputEventQueuer, ReadlineCmd, R_END_INPUT_FUNCTIONS, + CharEvent, CharInputStyle, ImplicitEvent, InputData, InputEventQueuer, ReadlineCmd, + R_END_INPUT_FUNCTIONS, }; use crate::key::{self, canonicalize_raw_escapes, ctrl, Key, Modifiers}; use crate::proc::job_reap; @@ -120,10 +121,6 @@ const fn make_md(name: &'static wstr, code: ReadlineCmd) -> InputFunctionMetadat /// Keep this list sorted alphabetically! #[rustfmt::skip] const INPUT_FUNCTION_METADATA: &[InputFunctionMetadata] = &[ - // NULL makes it unusable - this is specially inserted when we detect mouse input - make_md(L!(""), ReadlineCmd::DisableMouseTracking), - make_md(L!(""), ReadlineCmd::FocusIn), - make_md(L!(""), ReadlineCmd::FocusOut), make_md(L!("accept-autosuggestion"), ReadlineCmd::AcceptAutosuggestion), make_md(L!("and"), ReadlineCmd::FuncAnd), make_md(L!("backward-bigword"), ReadlineCmd::BackwardBigword), @@ -621,9 +618,10 @@ impl<'q, Queuer: InputEventQueuer + ?Sized> EventQueuePeeker<'q, Queuer> { /// Test if any of our peeked events are readline or check_exit. fn char_sequence_interrupted(&self) -> bool { - self.peeked - .iter() - .any(|evt| evt.is_readline_or_command() || evt.is_check_exit()) + self.peeked.iter().any(|evt| { + evt.is_readline_or_command() + || matches!(evt, CharEvent::Implicit(ImplicitEvent::CheckExit)) + }) } /// Reset our index back to 0. @@ -774,15 +772,6 @@ impl<'a> Reader<'a> { CharEvent::Command(_) => { return evt; } - CharEvent::Eof => { - // If we have EOF, we need to immediately quit. - // There's no need to go through the input functions. - return evt; - } - CharEvent::CheckExit => { - // Allow the reader to check for exit conditions. - return evt; - } CharEvent::Key(ref kevt) => { FLOG!( reader, @@ -797,6 +786,9 @@ impl<'a> Reader<'a> { self.push_front(evt); self.mapping_execute_matching_or_generic(); } + CharEvent::Implicit(_) => { + return evt; + } } } } diff --git a/src/input_common.rs b/src/input_common.rs index 2c43ee508..48854f029 100644 --- a/src/input_common.rs +++ b/src/input_common.rs @@ -130,10 +130,6 @@ pub enum ReadlineCmd { BeginUndoGroup, EndUndoGroup, RepeatJump, - DisableMouseTracking, - FocusIn, - FocusOut, - // ncurses uses the obvious name ClearScreenAndRepaint, // NOTE: This one has to be last. ReverseRepeatJump, @@ -180,6 +176,21 @@ pub struct KeyEvent { pub seq: WString, } +#[derive(Debug, Clone)] +pub enum ImplicitEvent { + /// end-of-file was reached. + Eof, + /// An event was handled internally, or an interrupt was received. Check to see if the reader + /// loop should exit. + CheckExit, + /// Our terminal window gained focus. + FocusIn, + /// Our terminal window lost focus. + FocusOut, + /// Request to disable mouse tracking. + DisableMouseTracking, +} + #[derive(Debug, Clone)] pub enum CharEvent { /// A character was entered. @@ -191,12 +202,8 @@ pub enum CharEvent { /// A shell command. Command(WString), - /// end-of-file was reached. - Eof, - - /// An event was handled internally, or an interrupt was received. Check to see if the reader - /// loop should exit. - CheckExit, + /// Any event that has no user-visible representation. + Implicit(ImplicitEvent), } impl CharEvent { @@ -204,14 +211,6 @@ impl CharEvent { matches!(self, CharEvent::Key(_)) } - pub fn is_eof(&self) -> bool { - matches!(self, CharEvent::Eof) - } - - pub fn is_check_exit(&self) -> bool { - matches!(self, CharEvent::CheckExit) - } - pub fn is_readline(&self) -> bool { matches!(self, CharEvent::Readline(_)) } @@ -273,7 +272,7 @@ impl CharEvent { } pub fn from_check_exit() -> CharEvent { - CharEvent::CheckExit + CharEvent::Implicit(ImplicitEvent::CheckExit) } } @@ -631,7 +630,7 @@ pub trait InputEventQueuer { let rr = readb(self.get_in_fd(), blocking); match rr { ReadbResult::Eof => { - return Some(CharEvent::Eof); + return Some(CharEvent::Implicit(ImplicitEvent::Eof)); } ReadbResult::Interrupted => { @@ -1028,11 +1027,11 @@ pub trait InputEventQueuer { } b'Z' => shift(key::Tab), b'I' => { - self.push_front(CharEvent::from_readline(ReadlineCmd::FocusIn)); + self.push_front(CharEvent::Implicit(ImplicitEvent::FocusIn)); return Some(Key::from_raw(key::Invalid)); } b'O' => { - self.push_front(CharEvent::from_readline(ReadlineCmd::FocusOut)); + self.push_front(CharEvent::Implicit(ImplicitEvent::FocusOut)); return Some(Key::from_raw(key::Invalid)); } _ => return None, @@ -1051,7 +1050,7 @@ pub trait InputEventQueuer { // We shouldn't directly manipulate stdout from here, so we ask the reader to do it. // writembs(outputter_t::stdoutput(), "\x1B[?1000l"); - self.push_front(CharEvent::from_readline(ReadlineCmd::DisableMouseTracking)); + self.push_front(CharEvent::Implicit(ImplicitEvent::DisableMouseTracking)); } fn parse_ss3(&mut self, buffer: &mut Vec) -> Option { @@ -1227,7 +1226,9 @@ pub trait InputEventQueuer { // Find the first sequence of non-char events. // EOF is considered a char: we don't want to pull EOF in front of real chars. let queue = &mut self.get_input_data_mut().queue; - let is_char = |evt: &CharEvent| evt.is_char() || evt.is_eof(); + let is_char = |evt: &CharEvent| { + evt.is_char() || matches!(evt, CharEvent::Implicit(ImplicitEvent::Eof)) + }; // Find the index of the first non-char event. // If there's none, we're done. let Some(first): Option = queue.iter().position(|e| !is_char(e)) else { diff --git a/src/reader.rs b/src/reader.rs index fcc608a2f..32dcd88d8 100644 --- a/src/reader.rs +++ b/src/reader.rs @@ -77,6 +77,7 @@ use crate::history::{ }; use crate::input::init_input; use crate::input_common::terminal_protocols_disable_ifn; +use crate::input_common::ImplicitEvent; use crate::input_common::IN_MIDNIGHT_COMMANDER_PRE_CSI_U; use crate::input_common::{ terminal_protocol_hacks, terminal_protocols_enable_ifn, CharEvent, CharInputStyle, InputData, @@ -2161,22 +2162,16 @@ impl<'a> Reader<'a> { let Some(event_needing_handling) = event_needing_handling else { return ControlFlow::Continue(()); }; - if event_needing_handling.is_check_exit() { - return ControlFlow::Continue(()); - } else if event_needing_handling.is_eof() { - reader_sighup(); - return ControlFlow::Continue(()); - } - - if !matches!( - self.rls().last_cmd, - Some(ReadlineCmd::Yank | ReadlineCmd::YankPop) - ) { - self.rls_mut().yank_len = 0; - } match event_needing_handling { CharEvent::Readline(readline_cmd_evt) => { + if !matches!( + self.rls().last_cmd, + Some(ReadlineCmd::Yank | ReadlineCmd::YankPop) + ) { + self.rls_mut().yank_len = 0; + } + let readline_cmd = readline_cmd_evt.cmd; if readline_cmd == ReadlineCmd::Cancel && self.is_navigating_pager_contents() { self.clear_transient_edit(); @@ -2230,9 +2225,23 @@ impl<'a> Reader<'a> { } self.rls_mut().last_cmd = None; } - CharEvent::Eof | CharEvent::CheckExit => { - panic!("Should have a char, readline or command") - } + CharEvent::Implicit(implicit_event) => match implicit_event { + ImplicitEvent::Eof => { + reader_sighup(); + } + ImplicitEvent::CheckExit => (), + ImplicitEvent::FocusIn => { + event::fire_generic(self.parser, L!("fish_focus_in").to_owned(), vec![]); + } + ImplicitEvent::FocusOut => { + event::fire_generic(self.parser, L!("fish_focus_out").to_owned(), vec![]); + } + ImplicitEvent::DisableMouseTracking => { + Outputter::stdoutput() + .borrow_mut() + .write_wstr(L!("\x1B[?1000l")); + } + }, } ControlFlow::Continue(()) } @@ -3437,17 +3446,6 @@ impl<'a> Reader<'a> { let (_elt, el) = self.active_edit_line_mut(); el.end_edit_group(); } - rl::DisableMouseTracking => { - Outputter::stdoutput() - .borrow_mut() - .write_wstr(L!("\x1B[?1000l")); - } - rl::FocusIn => { - event::fire_generic(self.parser, L!("fish_focus_in").to_owned(), vec![]); - } - rl::FocusOut => { - event::fire_generic(self.parser, L!("fish_focus_out").to_owned(), vec![]); - } rl::ClearScreenAndRepaint => { self.parser.libdata_mut().is_repaint = true; let clear = screen_clear(); @@ -5129,8 +5127,6 @@ fn command_ends_history_search(c: ReadlineCmd) -> bool { | rl::EndOfHistory | rl::Repaint | rl::ForceRepaint - | rl::FocusIn - | rl::FocusOut ) }