-
Notifications
You must be signed in to change notification settings - Fork 947
Fix background jobs segment #1254
Fix background jobs segment #1254
Conversation
We now trap if a child process was killed ("CLD") and use this to trigger prompt redraw, so that we always get the right number of background jobs. E.g. a `sleep 3&` shows the correct background job count, as soon as the background process was finished.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, this looks promising. @dritter, I agree with all of your points.
I expected that this would reset the prompt even if any program was called and then killed but it appears not to be the case (which is good).
LGTM
Olay. Thanks for review. Let's roll with that for a while and see how it turns out. |
There are corner cases that exhibit interesting behavior. E.g., this: unsetopt monitor
function TRAPALRM() { true & }
TMOUT=1 And of course there is the obvious problem of claiming a singleton resource ( |
@romkatv Thanks for the input. Yes, I think there are edge cases. Not sure how common these use cases are.. About singleton |
I'm afraid it's not possible in zsh. Global traps are off limits for plugins. At some point the workaround I used in Powerlevel10k was to embed a small script in
Here's a proof of concept: ❯ cat /tmp/poc/.zshrc
function set_prompt() {
typeset -ig N=0
local render_hook='${${${$((++N)):#2}:-$(echo second rendering >&2)}+}'
local actual_prompt='%m%# '
PROMPT="${render_hook}${actual_prompt}"
}
setopt promptsubst
autoload -Uz add-zsh-hook
add-zsh-hook precmd set_prompt
❯ ZDOTDIR=/tmp/poc zsh If you start a background job, you'll see "second rendering" printed to the console when it completes. Note that Unfortunately, you cannot simply replace P.S. It seems like these are the options for fixing background jobs in
|
This is ingenious (as ever)! I at least was missing the means to detect that second render.
You could do it with a handler: diff --git a/generator/default.p9k b/generator/default.p9k
index 718f6d7f..959ab9ca 100644
--- a/generator/default.p9k
+++ b/generator/default.p9k
@@ -437,7 +437,9 @@ local NEWLINE='
# For security $PROMPT is never set directly. This way the prompt render is
# forced to evaluate the variable and the contents of $__p9k_unsafe_PROMPT
# are never executed. The same applies to $RPROMPT.
- PROMPT='$__p9k_unsafe_PROMPT'
+ typeset -ig N=0
+ local render_hook='${${${$((++N)):#2}:-$( echo here we could trigger a handler >&2)}+}'
+ PROMPT="$render_hook"'${__p9k_unsafe_PROMPT}'
}
p9k::set_default P9K_IGNORE_TERM_COLORS false Sidenote: When I attempted to fix the |
What do you mean by handler? |
I was thinking something similar to the continually updating clock ( |
FWIW, the only way I managed to implement this handler is with the help of another process. Not pretty. |
Yeah, but in theory, the extra process just writes to the fifo every second to trigger the handler which isn't needed here. Not sure why it worked differently in my test, maybe I messed up somewhere. |
I don't think you messed up anywhere. If you write to the file during prompt expansion, the handler simply won't be called (bugs in zsh). You can revive the handler by sending zsh a signal (I used |
@romkatv Thanks for the hint. Little PoC, with no clean up done: diff --git a/generator/default.p9k b/generator/default.p9k
index 718f6d7f..b8947c7b 100644
--- a/generator/default.p9k
+++ b/generator/default.p9k
@@ -437,7 +437,9 @@ local NEWLINE='
# For security $PROMPT is never set directly. This way the prompt render is
# forced to evaluate the variable and the contents of $__p9k_unsafe_PROMPT
# are never executed. The same applies to $RPROMPT.
- PROMPT='$__p9k_unsafe_PROMPT'
+ typeset -ig N=0
+ local render_hook='${${${$((++N)):#2}:-$( zsh -c "sleep 1 && kill -WINCH $$ && echo" >'"$fifo"' 2>&1 &! )}+}'
+ PROMPT="$render_hook"'${__p9k_unsafe_PROMPT}'
}
p9k::set_default P9K_IGNORE_TERM_COLORS false
diff --git a/powerlevel9k.zsh-theme b/powerlevel9k.zsh-theme
index 4cbc2318..095c9883 100755
--- a/powerlevel9k.zsh-theme
+++ b/powerlevel9k.zsh-theme
@@ -189,6 +189,22 @@ esac
p9k::defined P9K_LEFT_PROMPT_ELEMENTS || P9K_LEFT_PROMPT_ELEMENTS=(context dir vcs)
p9k::defined P9K_RIGHT_PROMPT_ELEMENTS || P9K_RIGHT_PROMPT_ELEMENTS=(status root_indicator background_jobs history time)
+###########
+# PoC
+###########
+declare -g fifo
+fifo=$(mktemp -u "${TMPDIR:-/tmp}"/p9k.$$.pipe.time.XXXXXXXXXX)
+mkfifo $fifo
+exec {__p9k_prompt_reset_hook}<>$fifo
+typeset -gfH __p9k_reset_prompt() {
+ # reset prompt on pipe update
+ emulate -L zsh
+ local _
+ IFS='' read -u $__p9k_prompt_reset_hook _ \
+ && __p9k_background_jobs && __p9k_prepare_prompts && zle && zle .reset-prompt
+}
+zle -F $__p9k_prompt_reset_hook __p9k_reset_prompt
+
################################################################
# Load Prompt Segment Definitions
################################################################ |
👍 |
@dritter I think @romkatv listed pretty much all the possibilities in #1254 (comment). What do you think? What should we go with? Fixed enough for now and live with the consequences until #1176 or something else? |
Sorry for the delay. And thanks @romkatv for explaining the options in detail.
Well, the fix with the trap is already merged. We could revert that, obviously, but I would rather go with the trap.
That would be a no-go for me. I've seen more issues about incorrect CTRL-C behavior than about background_jobs not working right.
That is the status quo now in
This is probably a good solution, if we can render the segments individually. But that is - as @Syphdias suggests - something for #1176 .
That is somewhat too extreme for my taste. So, overall I would live with the trap for the moment, and add render detection once we have #1176 . WDYT @Syphdias ? |
I agree. I would rather react fast to complaints than to delay further. I'm still a fan of speeding up the release cycle (a lot). |
The
background_jobs
segment now reports the jobs count immediately. We trapCLD
(Child process was killed) here, taken from here.Caveat: It might cause some trouble, if in multiline-prompts (cursor position changes, when we show the segment).
Performancewise, this redraws the complete prompt on every child exit (solvable in #1176 ).
I haven't tested it much (running out of time again), and I am not a fan of trapping signals all over, but that seems to be our only chance..
// cc @Syphdias
Fixes #1196 .
Succeeds #1238 .