mirror of
https://github.com/fish-shell/fish-shell.git
synced 2026-06-07 10:01:14 -03:00
Process shell commands from bindings like regular char events
A long standing issue is that bindings cannot mix special input functions
and shell commands. For example,
bind x end-of-line "commandline -i x"
silently does nothing. Instead we have to do lift everything to shell commands
bind x "commandline -f end-of-line; commandline -i x"
for no good reason.
Additionally, there is a weird ordering difference between special input
functions and shell commands. Special input functions are pushed into the
the queue whereas shell commands are executed immediately.
This weird ordering means that the above "bind x" still doesn't work as
expected, because "commandline -i" is processed before "end-of-line".
Finally, this is all implemented via weird hack to allow recursive use of
a mutable reference to the reader state.
Fix all of this by processing shell commands the same as both special input
functions and regular chars. Hopefully this doesn't break anything.
Fixes #8186
Fixes #10360
Closes #9398
This commit is contained in:
@@ -116,7 +116,7 @@ pub enum ReadlineCmd {
|
||||
}
|
||||
|
||||
/// Represents an event on the character input stream.
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum CharEventType {
|
||||
/// A character was entered.
|
||||
Char(char),
|
||||
@@ -124,6 +124,12 @@ pub enum CharEventType {
|
||||
/// A readline event.
|
||||
Readline(ReadlineCmd),
|
||||
|
||||
/// A shell command.
|
||||
Command(WString),
|
||||
|
||||
/// A request to change the input mapping mode.
|
||||
SetMode(WString),
|
||||
|
||||
/// end-of-file was reached.
|
||||
Eof,
|
||||
|
||||
@@ -162,6 +168,13 @@ pub fn is_readline(&self) -> bool {
|
||||
matches!(self.evt, CharEventType::Readline(_))
|
||||
}
|
||||
|
||||
pub fn is_readline_or_command(&self) -> bool {
|
||||
matches!(
|
||||
self.evt,
|
||||
CharEventType::Readline(_) | CharEventType::Command(_) | CharEventType::SetMode(_)
|
||||
)
|
||||
}
|
||||
|
||||
pub fn get_char(&self) -> char {
|
||||
let CharEventType::Char(c) = self.evt else {
|
||||
panic!("Not a char type");
|
||||
@@ -184,6 +197,20 @@ pub fn get_readline(&self) -> ReadlineCmd {
|
||||
c
|
||||
}
|
||||
|
||||
pub fn get_command(&self) -> Option<&wstr> {
|
||||
match &self.evt {
|
||||
CharEventType::Command(c) => Some(c),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_mode(&self) -> Option<&wstr> {
|
||||
match &self.evt {
|
||||
CharEventType::SetMode(m) => Some(m),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_char(c: char) -> CharEvent {
|
||||
CharEvent {
|
||||
evt: CharEventType::Char(c),
|
||||
@@ -204,6 +231,22 @@ pub fn from_readline_seq(cmd: ReadlineCmd, seq: WString) -> CharEvent {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_command(cmd: WString) -> CharEvent {
|
||||
CharEvent {
|
||||
evt: CharEventType::Command(cmd),
|
||||
input_style: CharInputStyle::Normal,
|
||||
seq: WString::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_set_mode(mode: WString) -> CharEvent {
|
||||
CharEvent {
|
||||
evt: CharEventType::SetMode(mode),
|
||||
input_style: CharInputStyle::Normal,
|
||||
seq: WString::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_check_exit() -> CharEvent {
|
||||
CharEvent {
|
||||
evt: CharEventType::CheckExit,
|
||||
@@ -587,7 +630,7 @@ fn insert_front<I>(&mut self, evts: I)
|
||||
fn drop_leading_readline_events(&mut self) {
|
||||
let queue = self.get_queue_mut();
|
||||
while let Some(evt) = queue.front() {
|
||||
if evt.is_readline() {
|
||||
if evt.is_readline_or_command() {
|
||||
queue.pop_front();
|
||||
} else {
|
||||
break;
|
||||
|
||||
Reference in New Issue
Block a user