fix: iris stops working after exec a command in bash (#66)

Fix #65

when the user presses Enter to run a command, Iris sets `isCommandActive
= true` so it knows a command is running and skips rendering the
overlay. After the command finishes, `isCommandActive` needs to reset to
`false` for Iris to work again. In zsh/fish, preexec/precmd hooks send
an `IRIS_CMD_STOP` signal over the IPC pipe, which Iris receives to
reset `isCommandActive = false`. Bash has no equivalent hook, so
`IRIS_CMD_STOP` is never sent and `isCommandActive` stays stuck at true
forever

so I added a bash-only fallback inside `isExecuting()`: if
`isCommandActive` is true but `TIOCGPGRP` (a kernel API) confirms the
shell's process group is back in the foreground (meaning the command
finished), automatically reset `isCommandActive` to false. zsh/fish
still rely on IPC signals as before

also added a `PROMPT_COMMAND` hook to iris init bash to `send
IRIS_CMD_STOP` after every command (belt-and-suspenders), though that's
not the main fix
This commit is contained in:
VERSE
2026-07-29 23:00:13 +07:00
committed by GitHub
parent d73921e419
commit 812d73b42a
2 changed files with 20 additions and 0 deletions
+12
View File
@@ -71,6 +71,18 @@ if [ -z "$IRIS_PID" ] && [ -z "$IRIS_RESCUE" ]; then
export IRIS_ACTIVE_SHELL="bash" export IRIS_ACTIVE_SHELL="bash"
exec iris exec iris
fi fi
# Iris Autocomplete Hook
if [ -n "$IRIS_PID" ] && [ -n "$IRIS_FD" ]; then
_iris_bash_precmd() {
printf "IRIS_CMD_STOP\x00" >&$IRIS_FD 2>/dev/null
}
if [[ ";$PROMPT_COMMAND;" != *";_iris_bash_precmd;"* ]]; then
PROMPT_COMMAND="_iris_bash_precmd${PROMPT_COMMAND:+;$PROMPT_COMMAND}"
fi
fi
`) `)
case "fish": case "fish":
fmt.Printf(` fmt.Printf(`
+8
View File
@@ -287,6 +287,14 @@ func runWrapper() {
renderOverlay := func() {} renderOverlay := func() {}
isExecuting := func() bool { isExecuting := func() bool {
if isCommandActive.Load() { if isCommandActive.Load() {
// for bash: no preexec/precmd hooks, so fall back to TIOCGPGRP to detect when shell returns
if shellName == "bash" {
pgrp, pgrpErr := unix.IoctlGetInt(int(ptmx.Fd()), unix.TIOCGPGRP)
if pgrpErr == nil && pgrp == shellPGID {
isCommandActive.Store(false)
return false
}
}
return true return true
} }
pgrp, err := unix.IoctlGetInt(int(ptmx.Fd()), unix.TIOCGPGRP) pgrp, err := unix.IoctlGetInt(int(ptmx.Fd()), unix.TIOCGPGRP)