mirror of
https://github.com/fish-shell/fish-shell
synced 2025-01-12 13:08:49 +00:00
Move some fake readline commands to a separate type
This commit is contained in:
parent
48ae19b4b1
commit
ca9c5f4cec
3 changed files with 59 additions and 70 deletions
26
src/input.rs
26
src/input.rs
|
@ -4,7 +4,8 @@ use crate::env::{Environment, CURSES_INITIALIZED};
|
||||||
use crate::event;
|
use crate::event;
|
||||||
use crate::flog::FLOG;
|
use crate::flog::FLOG;
|
||||||
use crate::input_common::{
|
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::key::{self, canonicalize_raw_escapes, ctrl, Key, Modifiers};
|
||||||
use crate::proc::job_reap;
|
use crate::proc::job_reap;
|
||||||
|
@ -120,10 +121,6 @@ const fn make_md(name: &'static wstr, code: ReadlineCmd) -> InputFunctionMetadat
|
||||||
/// Keep this list sorted alphabetically!
|
/// Keep this list sorted alphabetically!
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
const INPUT_FUNCTION_METADATA: &[InputFunctionMetadata] = &[
|
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!("accept-autosuggestion"), ReadlineCmd::AcceptAutosuggestion),
|
||||||
make_md(L!("and"), ReadlineCmd::FuncAnd),
|
make_md(L!("and"), ReadlineCmd::FuncAnd),
|
||||||
make_md(L!("backward-bigword"), ReadlineCmd::BackwardBigword),
|
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.
|
/// Test if any of our peeked events are readline or check_exit.
|
||||||
fn char_sequence_interrupted(&self) -> bool {
|
fn char_sequence_interrupted(&self) -> bool {
|
||||||
self.peeked
|
self.peeked.iter().any(|evt| {
|
||||||
.iter()
|
evt.is_readline_or_command()
|
||||||
.any(|evt| evt.is_readline_or_command() || evt.is_check_exit())
|
|| matches!(evt, CharEvent::Implicit(ImplicitEvent::CheckExit))
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reset our index back to 0.
|
/// Reset our index back to 0.
|
||||||
|
@ -774,15 +772,6 @@ impl<'a> Reader<'a> {
|
||||||
CharEvent::Command(_) => {
|
CharEvent::Command(_) => {
|
||||||
return evt;
|
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) => {
|
CharEvent::Key(ref kevt) => {
|
||||||
FLOG!(
|
FLOG!(
|
||||||
reader,
|
reader,
|
||||||
|
@ -797,6 +786,9 @@ impl<'a> Reader<'a> {
|
||||||
self.push_front(evt);
|
self.push_front(evt);
|
||||||
self.mapping_execute_matching_or_generic();
|
self.mapping_execute_matching_or_generic();
|
||||||
}
|
}
|
||||||
|
CharEvent::Implicit(_) => {
|
||||||
|
return evt;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -130,10 +130,6 @@ pub enum ReadlineCmd {
|
||||||
BeginUndoGroup,
|
BeginUndoGroup,
|
||||||
EndUndoGroup,
|
EndUndoGroup,
|
||||||
RepeatJump,
|
RepeatJump,
|
||||||
DisableMouseTracking,
|
|
||||||
FocusIn,
|
|
||||||
FocusOut,
|
|
||||||
// ncurses uses the obvious name
|
|
||||||
ClearScreenAndRepaint,
|
ClearScreenAndRepaint,
|
||||||
// NOTE: This one has to be last.
|
// NOTE: This one has to be last.
|
||||||
ReverseRepeatJump,
|
ReverseRepeatJump,
|
||||||
|
@ -180,6 +176,21 @@ pub struct KeyEvent {
|
||||||
pub seq: WString,
|
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)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum CharEvent {
|
pub enum CharEvent {
|
||||||
/// A character was entered.
|
/// A character was entered.
|
||||||
|
@ -191,12 +202,8 @@ pub enum CharEvent {
|
||||||
/// A shell command.
|
/// A shell command.
|
||||||
Command(WString),
|
Command(WString),
|
||||||
|
|
||||||
/// end-of-file was reached.
|
/// Any event that has no user-visible representation.
|
||||||
Eof,
|
Implicit(ImplicitEvent),
|
||||||
|
|
||||||
/// An event was handled internally, or an interrupt was received. Check to see if the reader
|
|
||||||
/// loop should exit.
|
|
||||||
CheckExit,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CharEvent {
|
impl CharEvent {
|
||||||
|
@ -204,14 +211,6 @@ impl CharEvent {
|
||||||
matches!(self, CharEvent::Key(_))
|
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 {
|
pub fn is_readline(&self) -> bool {
|
||||||
matches!(self, CharEvent::Readline(_))
|
matches!(self, CharEvent::Readline(_))
|
||||||
}
|
}
|
||||||
|
@ -273,7 +272,7 @@ impl CharEvent {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_check_exit() -> 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);
|
let rr = readb(self.get_in_fd(), blocking);
|
||||||
match rr {
|
match rr {
|
||||||
ReadbResult::Eof => {
|
ReadbResult::Eof => {
|
||||||
return Some(CharEvent::Eof);
|
return Some(CharEvent::Implicit(ImplicitEvent::Eof));
|
||||||
}
|
}
|
||||||
|
|
||||||
ReadbResult::Interrupted => {
|
ReadbResult::Interrupted => {
|
||||||
|
@ -1028,11 +1027,11 @@ pub trait InputEventQueuer {
|
||||||
}
|
}
|
||||||
b'Z' => shift(key::Tab),
|
b'Z' => shift(key::Tab),
|
||||||
b'I' => {
|
b'I' => {
|
||||||
self.push_front(CharEvent::from_readline(ReadlineCmd::FocusIn));
|
self.push_front(CharEvent::Implicit(ImplicitEvent::FocusIn));
|
||||||
return Some(Key::from_raw(key::Invalid));
|
return Some(Key::from_raw(key::Invalid));
|
||||||
}
|
}
|
||||||
b'O' => {
|
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 Some(Key::from_raw(key::Invalid));
|
||||||
}
|
}
|
||||||
_ => return None,
|
_ => 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.
|
// We shouldn't directly manipulate stdout from here, so we ask the reader to do it.
|
||||||
// writembs(outputter_t::stdoutput(), "\x1B[?1000l");
|
// 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<u8>) -> Option<Key> {
|
fn parse_ss3(&mut self, buffer: &mut Vec<u8>) -> Option<Key> {
|
||||||
|
@ -1227,7 +1226,9 @@ pub trait InputEventQueuer {
|
||||||
// Find the first sequence of non-char events.
|
// 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.
|
// 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 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.
|
// Find the index of the first non-char event.
|
||||||
// If there's none, we're done.
|
// If there's none, we're done.
|
||||||
let Some(first): Option<usize> = queue.iter().position(|e| !is_char(e)) else {
|
let Some(first): Option<usize> = queue.iter().position(|e| !is_char(e)) else {
|
||||||
|
|
|
@ -77,6 +77,7 @@ use crate::history::{
|
||||||
};
|
};
|
||||||
use crate::input::init_input;
|
use crate::input::init_input;
|
||||||
use crate::input_common::terminal_protocols_disable_ifn;
|
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::IN_MIDNIGHT_COMMANDER_PRE_CSI_U;
|
||||||
use crate::input_common::{
|
use crate::input_common::{
|
||||||
terminal_protocol_hacks, terminal_protocols_enable_ifn, CharEvent, CharInputStyle, InputData,
|
terminal_protocol_hacks, terminal_protocols_enable_ifn, CharEvent, CharInputStyle, InputData,
|
||||||
|
@ -2161,13 +2162,9 @@ impl<'a> Reader<'a> {
|
||||||
let Some(event_needing_handling) = event_needing_handling else {
|
let Some(event_needing_handling) = event_needing_handling else {
|
||||||
return ControlFlow::Continue(());
|
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(());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
match event_needing_handling {
|
||||||
|
CharEvent::Readline(readline_cmd_evt) => {
|
||||||
if !matches!(
|
if !matches!(
|
||||||
self.rls().last_cmd,
|
self.rls().last_cmd,
|
||||||
Some(ReadlineCmd::Yank | ReadlineCmd::YankPop)
|
Some(ReadlineCmd::Yank | ReadlineCmd::YankPop)
|
||||||
|
@ -2175,8 +2172,6 @@ impl<'a> Reader<'a> {
|
||||||
self.rls_mut().yank_len = 0;
|
self.rls_mut().yank_len = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
match event_needing_handling {
|
|
||||||
CharEvent::Readline(readline_cmd_evt) => {
|
|
||||||
let readline_cmd = readline_cmd_evt.cmd;
|
let readline_cmd = readline_cmd_evt.cmd;
|
||||||
if readline_cmd == ReadlineCmd::Cancel && self.is_navigating_pager_contents() {
|
if readline_cmd == ReadlineCmd::Cancel && self.is_navigating_pager_contents() {
|
||||||
self.clear_transient_edit();
|
self.clear_transient_edit();
|
||||||
|
@ -2230,9 +2225,23 @@ impl<'a> Reader<'a> {
|
||||||
}
|
}
|
||||||
self.rls_mut().last_cmd = None;
|
self.rls_mut().last_cmd = None;
|
||||||
}
|
}
|
||||||
CharEvent::Eof | CharEvent::CheckExit => {
|
CharEvent::Implicit(implicit_event) => match implicit_event {
|
||||||
panic!("Should have a char, readline or command")
|
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(())
|
ControlFlow::Continue(())
|
||||||
}
|
}
|
||||||
|
@ -3437,17 +3446,6 @@ impl<'a> Reader<'a> {
|
||||||
let (_elt, el) = self.active_edit_line_mut();
|
let (_elt, el) = self.active_edit_line_mut();
|
||||||
el.end_edit_group();
|
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 => {
|
rl::ClearScreenAndRepaint => {
|
||||||
self.parser.libdata_mut().is_repaint = true;
|
self.parser.libdata_mut().is_repaint = true;
|
||||||
let clear = screen_clear();
|
let clear = screen_clear();
|
||||||
|
@ -5129,8 +5127,6 @@ fn command_ends_history_search(c: ReadlineCmd) -> bool {
|
||||||
| rl::EndOfHistory
|
| rl::EndOfHistory
|
||||||
| rl::Repaint
|
| rl::Repaint
|
||||||
| rl::ForceRepaint
|
| rl::ForceRepaint
|
||||||
| rl::FocusIn
|
|
||||||
| rl::FocusOut
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue