T34: review round 2: bash 3.2 drops its DEBUG trap, which ran for key bindings, missed lone subshells and decided commands under extdebug, so it sends no C, and its D comes from the prompt by the command number; PowerShell takes a program's code only when the line's last pipeline ends in it, as its syntax tree and Get-Command name it; each check waits for the prompt before its line, so a repeated status is the line's own
CI / platforms (ubuntu-24.04) (push) Successful in 1m35s
CI / platforms (windows-latest) (push) Successful in 1m41s
CI / macos (push) Successful in 11m11s

This commit is contained in:
ZacharyZhang-NY committed 2026-10-16 23:13:42 -04:00
1 parent 0a22200725
commit d4bc6e69fa
6 files changed
+89 -45

No files matched your search

+4 -23
View File
@@ -13,37 +13,19 @@ else
[ -r ~/.bashrc ] && builtin source ~/.bashrc
fi
_ely_ran=
_ely_sent=
_ely_n=0
_ely_armed=
_ely_ps0=
if (( BASH_VERSINFO[0] * 100 + BASH_VERSINFO[1] >= 404 )); then
# PS0 runs in the shell, so its subscript can note that a command ran.
_ely_ps0='${_ely_note[_ely_ran=1]-}\e]133;C\a'
else
# bash 3.2 has no PS0: the DEBUG trap sends C, then runs the user's own trap with $? and $_ kept.
_ely_debug() {
builtin local status=$?
if [ -n "$_ely_armed" ] && [[ $BASH_COMMAND != _ely_* ]]; then
_ely_armed=
_ely_ran=1
builtin printf '\e]133;C\a'
fi
builtin return $status
}
builtin eval "_ely_trap=($(builtin trap -p DEBUG))"
builtin trap "_ely_debug \"\$_\"${_ely_trap[2]:+; ${_ely_trap[2]}}" DEBUG
builtin unset _ely_trap
fi
_ely_prompt() {
builtin local ret=$? LC_ALL=C char url= i title
_ely_armed=
_ely_sent=$_ely_ran
if [ -n "$_ely_ran" ]; then
builtin printf '\e]133;D;%s\a' "$ret"
_ely_ran=
fi
_ely_d=([1]=$'\e]133;D;'"$ret"$'\a')
[ -n "$_ely_ps0" ] || _ely_d=([1]=$'\e]133;D;'"$ret"$'\a')
for (( i = 0; i < ${#PWD}; i++ )); do
char=${PWD:i:1}
case $char in
@@ -58,9 +40,9 @@ _ely_prompt() {
# Last, after anything that sets PS1 or PS0.
_ely_mark() {
if [[ $PS1 != *'\e]133;A'* ]]; then
if builtin shopt -q promptvars; then
# bash 3.2 traps no line that is only a subshell; \# counts it, so the prompt sends its D.
PS1='\[${_ely_d[!_ely_sent && _ely_n && \# != _ely_n]-}${_ely_note[_ely_n = \#]-}\e]133;A\a\]'"$PS1"'\[\e]133;B\a\]'
if [ -z "$_ely_ps0" ] && builtin shopt -q promptvars; then
# bash 3.2 has no PS0; \#, the command number, moves once a command ran.
PS1='\[${_ely_d[_ely_n && \# != _ely_n]-}${_ely_note[_ely_n = \#]-}\e]133;A\a\]'"$PS1"'\[\e]133;B\a\]'
else
PS1='\[\e]133;A\a\]'"$PS1"'\[\e]133;B\a\]'
fi
@@ -68,6 +50,5 @@ _ely_mark() {
if [ -n "$_ely_ps0" ] && builtin shopt -q promptvars && [[ ${PS0-} != *"$_ely_ps0"* ]]; then
PS0=$_ely_ps0${PS0-}
fi
_ely_armed=1
}
PROMPT_COMMAND="_ely_prompt${PROMPT_COMMAND:+;$PROMPT_COMMAND};_ely_mark"
+15 -1
View File
@@ -11,7 +11,7 @@ function global:prompt {
# Each native run sets a new $LASTEXITCODE, equal or not; strict mode refuses an unset one.
$exit = Get-Variable LASTEXITCODE -Scope Global -ValueOnly -ErrorAction Ignore
$ran = $null -ne $exit -and -not [object]::ReferenceEquals($exit, $global:ElyExit)
$code = if ($ran -and $exit -ne 0) { $exit } else { 1 }
$code = if ($global:ElyNative -and $ran -and $exit -ne 0) { $exit } else { 1 }
}
[Console]::Write("$esc]133;D;$code$bel")
$global:ElyRan = $false
@@ -38,6 +38,20 @@ if (Test-Path Function:\PSConsoleHostReadLine) {
if (-not [string]::IsNullOrWhiteSpace($line)) {
$global:ElyRan = $true
$global:ElyExit = Get-Variable LASTEXITCODE -Scope Global -ValueOnly -ErrorAction Ignore
# A program's exit code is the line's when the line's last pipeline ends in it.
$global:ElyNative = $false
$ast = [System.Management.Automation.Language.Parser]::ParseInput($line, [ref]$null, [ref]$null)
# Strict mode refuses .Count on one statement alone, so the statements stay a list.
$statements = @(if ($ast.EndBlock) { $ast.EndBlock.Statements })
$last = if ($statements.Count) { $statements[$statements.Count - 1] }
if ($last -is [System.Management.Automation.Language.PipelineAst]) {
$elements = $last.PipelineElements
$end = $elements[$elements.Count - 1]
$name = if ($end -is [System.Management.Automation.Language.CommandAst]) { $end.GetCommandName() }
$info = if ($name) { Get-Command -Name $name -ErrorAction Ignore | Select-Object -First 1 }
while ($info -and $info.CommandType -eq 'Alias') { $info = $info.ResolvedCommand }
$global:ElyNative = $null -ne $info -and $info.CommandType -in 'Application', 'ExternalScript'
}
[Console]::Write("$([char]27)]133;C$([char]7)")
}
$line