Send repaint requests through the input queue again

Another consequence of a583fe723 ("commandline -f foo" to skip queue
and execute immediately, 2024-04-08) is that "commandline -f repaint"
will paint the prompt with the current value of $status which might be
set from a shell command in a the currently executing binding, instead of
waiting for the top-level status. This is wrong, at least historically. It
surfaces in bindings like alt-w which always paint a status value of [1]
when on single-lines commandlines.

Another regression is that a redundant repaint in a signal handler outputs
an extra prompt.

Fix both by making repaint commands go over the input queue again.  This way,
they are always run with a good commandline state.  There is no need to
repaint immediately because I don't think anyone has a data dependency on it
(we currently don't expose the prompt string), it's only for rendering.
This commit is contained in:
Johannes Altmanninger 2024-04-19 11:25:05 +02:00
parent 040cb04423
commit 5ba21cd290
3 changed files with 52 additions and 3 deletions

View File

@ -903,6 +903,19 @@ pub fn reader_schedule_prompt_repaint() {
pub fn reader_execute_readline_cmd(ch: CharEvent) { pub fn reader_execute_readline_cmd(ch: CharEvent) {
if let Some(data) = current_data() { if let Some(data) = current_data() {
let CharEvent::Readline(readline_cmd_evt) = &ch else {
panic!()
};
if matches!(
readline_cmd_evt.cmd,
ReadlineCmd::ClearScreenAndRepaint
| ReadlineCmd::RepaintMode
| ReadlineCmd::Repaint
| ReadlineCmd::ForceRepaint
) {
data.inputter.queue_char(ch);
return;
}
if data.rls.is_none() { if data.rls.is_none() {
data.rls = Some(ReadlineLoopState::new()); data.rls = Some(ReadlineLoopState::new());
} }

View File

@ -2,19 +2,37 @@
#REQUIRES: command -v tmux #REQUIRES: command -v tmux
set -g isolated_tmux_fish_extra_args -C ' set -g isolated_tmux_fish_extra_args -C '
function fish_prompt; printf "prompt $status_generation> <$prompt_var> "; end function fish_prompt
printf "prompt $status_generation> <status=$status> <$prompt_var> "
set prompt_var ''
end
function on_prompt_var --on-variable prompt_var function on_prompt_var --on-variable prompt_var
commandline -f repaint commandline -f repaint
end end
function token-info
__fish_echo echo "current token is <$(commandline -t)>"
end
bind ctrl-g token-info
' '
isolated-tmux-start isolated-tmux-start
isolated-tmux capture-pane -p isolated-tmux capture-pane -p
# CHECK: prompt 0> <> # CHECK: prompt 0> <status=0> <>
set -q CI && set sleep sleep 10 set -q CI && set sleep sleep 10
set -U prompt_var changed set -U prompt_var changed
tmux-sleep tmux-sleep
isolated-tmux send-keys Enter
# CHECK: prompt 0> <status=0> <changed>
isolated-tmux send-keys echo Space 123
tmux-sleep
isolated-tmux send-keys C-g
# CHECK: prompt 0> <status=0> <> echo 123
# CHECK: current token is <123>
# CHECK: prompt 0> <status=0> <> echo 123
tmux-sleep
isolated-tmux capture-pane -p isolated-tmux capture-pane -p
# CHECK: prompt 0> <changed>

View File

@ -0,0 +1,18 @@
#RUN: %fish %s
#REQUIRES: command -v tmux
isolated-tmux-start
isolated-tmux send-keys '
function usr1_handler --on-signal SIGUSR1
echo Got SIGUSR1
# This repaint is not needed but make sure it is coalesced.
commandline -f repaint
end
' Enter
isolated-tmux send-keys C-l 'kill -SIGUSR1 $fish_pid' Enter
tmux-sleep
isolated-tmux capture-pane -p
# CHECK: prompt 1> kill -SIGUSR1 $fish_pid
# CHECK: Got SIGUSR1
# CHECK: prompt 2>