mirror of
https://github.com/fish-shell/fish-shell
synced 2024-12-27 05:13:10 +00:00
"commandline -f foo" to skip queue and execute immediately
Commit c3cd68dda
(Process shell commands from bindings like regular char
events, 2024-03-02) mentions a "weird ordering difference".
The issue is that "commandline -f foo" goes through the input
queue while other commands are executed directly.
For example
bind ctrl-g "commandline -f end-of-line; commandline -i x"
is executed in the wrong order. Fix that.
This doesn't yet work for "commandline -f exit" but that can be fixed easily.
It's hard to imagine anyone would rely on the existing behavior. "commandline
-f" in bindings is mostly used for repainting the commandline.
This commit is contained in:
parent
9d7116c12d
commit
a583fe7230
4 changed files with 34 additions and 10 deletions
|
@ -107,6 +107,8 @@ Interactive improvements
|
|||
New or improved bindings
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
- Bindings can now mix special input functions and shell commands, so ``bind ctrl-g expand-abbr "commandline -i \n"`` works as expected (:issue:`8186`).
|
||||
- Special input functions run from bindings via ``commandline -f`` are now applied immediately instead of after the currently executing binding.
|
||||
For example, ``commandline -f yank -f yank-pop`` inserts the last-but-one entry from the kill ring.
|
||||
- When the cursor is on a command that resolves to an executable script, :kbd:`Alt-O` will now open that script in your editor (:issue:`10266`).
|
||||
- Two improvements to the :kbd:`Alt-E` binding which edits the commandline in an external editor:
|
||||
- The editor's cursor position is copied back to fish. This is currently supported for Vim and Kakoune.
|
||||
|
|
|
@ -12,7 +12,8 @@ use crate::parse_util::{
|
|||
};
|
||||
use crate::proc::is_interactive_session;
|
||||
use crate::reader::{
|
||||
commandline_get_state, commandline_set_buffer, commandline_set_search_field, reader_queue_ch,
|
||||
commandline_get_state, commandline_set_buffer, commandline_set_search_field,
|
||||
reader_execute_readline_cmd,
|
||||
};
|
||||
use crate::tokenizer::TOK_ACCEPT_UNFINISHED;
|
||||
use crate::tokenizer::{TokenType, Tokenizer};
|
||||
|
@ -298,8 +299,6 @@ pub fn commandline(parser: &Parser, streams: &mut IoStreams, args: &mut [&wstr])
|
|||
|
||||
let positional_args = w.argv.len() - w.woptind;
|
||||
|
||||
let ld = parser.libdata();
|
||||
|
||||
if function_mode {
|
||||
// Check for invalid switch combinations.
|
||||
if buffer_part.is_some()
|
||||
|
@ -335,13 +334,13 @@ pub fn commandline(parser: &Parser, streams: &mut IoStreams, args: &mut [&wstr])
|
|||
// Don't enqueue a repaint if we're currently in the middle of one,
|
||||
// because that's an infinite loop.
|
||||
if matches!(cmd, rl::RepaintMode | rl::ForceRepaint | rl::Repaint) {
|
||||
if ld.pods.is_repaint {
|
||||
if parser.libdata().pods.is_repaint {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Inserts the readline function at the back of the queue.
|
||||
reader_queue_ch(CharEvent::from_readline(cmd));
|
||||
reader_execute_readline_cmd(CharEvent::from_readline(cmd));
|
||||
}
|
||||
|
||||
return STATUS_CMD_OK;
|
||||
|
@ -473,8 +472,13 @@ pub fn commandline(parser: &Parser, streams: &mut IoStreams, args: &mut [&wstr])
|
|||
} else if let Some(override_buffer) = &override_buffer {
|
||||
current_buffer = override_buffer;
|
||||
current_cursor_pos = current_buffer.len();
|
||||
} else if !ld.transient_commandlines.is_empty() && !cursor_mode {
|
||||
transient = ld.transient_commandlines.last().unwrap().clone();
|
||||
} else if !parser.libdata().transient_commandlines.is_empty() && !cursor_mode {
|
||||
transient = parser
|
||||
.libdata()
|
||||
.transient_commandlines
|
||||
.last()
|
||||
.unwrap()
|
||||
.clone();
|
||||
current_buffer = &transient;
|
||||
current_cursor_pos = transient.len();
|
||||
} else if rstate.initialized {
|
||||
|
|
|
@ -904,10 +904,14 @@ pub fn reader_schedule_prompt_repaint() {
|
|||
}
|
||||
}
|
||||
|
||||
/// Enqueue an event to the back of the reader's input queue.
|
||||
pub fn reader_queue_ch(ch: CharEvent) {
|
||||
pub fn reader_execute_readline_cmd(ch: CharEvent) {
|
||||
if let Some(data) = current_data() {
|
||||
data.inputter.queue_char(ch);
|
||||
if data.rls.is_none() {
|
||||
data.rls = Some(ReadlineLoopState::new());
|
||||
}
|
||||
data.apply_commandline_state_changes();
|
||||
data.handle_char_event(Some(ch));
|
||||
data.update_commandline_state();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -358,6 +358,20 @@ send('\x02\x02\x02') # ctrl-b, backward-char
|
|||
sendline('\x1bu') # alt+u, upcase word
|
||||
expect_prompt("fooBAR")
|
||||
|
||||
send("""
|
||||
bind ctrl-g "
|
||||
commandline --insert 'echo foo ar'
|
||||
commandline -f backward-word
|
||||
commandline --insert b
|
||||
commandline -f backward-char
|
||||
commandline -f backward-char
|
||||
commandline -f delete-char
|
||||
"
|
||||
""")
|
||||
send('\x07') # ctrl-g
|
||||
send('\r')
|
||||
expect_prompt("foobar")
|
||||
|
||||
# Check that the builtin version of `exit` works
|
||||
# (for obvious reasons this MUST BE LAST)
|
||||
sendline("function myexit; echo exit; exit; end; bind ctrl-z myexit")
|
||||
|
|
Loading…
Reference in a new issue