Не устанавливайте $? на ненулевое значение при нажатии Control+C

Не устанавливайте $? на ненулевое значение при нажатии Control+C

Мой $PS1в Zsh включает это выражение: %(?. %?.) Это означает «если код выхода предыдущей команды ( $?) истинен, показывать $?, иначе ничего не показывать». Это, как правило, полезно, но меня раздражает одна вещь: оболочки устанавливают код возврата последней команды на ненулевой, когда я нажимаю Control+C без запуска команды! Zsh устанавливает его в 1, Bash устанавливает его в 130. Dash — единственная оболочка в моей системе, которая не сбрасывает его при нажатии Control+C.

Как размножать:

  1. Запустите zsh или bash.
  2. Нажмите Control+C.
  3. echo $?.

Есть ли способ отключить это поведение в Zsh?

решение1

Я не думаю, что есть способ это отключить.

Первая мысль — чтобы preexec установил переменную, которая указывает на то, что команда была запущена. Если нажать Ctrl+C в приглашении, она не будет установлена.

precmd() {
    exit_status=$?
    if ! $ran_something; then
        exit_status=0
    fi
    ran_something=false
}
preexec() {
    ran_something=true
}
show_non_zero_exit_status() {
    case $exit_status in
    0)
        :;;
    *)
        echo $exit_status;;
    esac
}
PS1='$(show_non_zero_exit_status)$ '

Но есть и другая похожая проблема: если вы приостановите команду, вы получите код выхода 20 (zsh < 5.0.7) или 148 (bash и zsh >= 5.0.7).

Чтобы обойти это, вы можете добавить 20|148к caseприведенному выше утверждению, т.е.

show_non_zero_exit_status() {
    case $exit_status in
    0|20|148)
        :;;
    *)
        echo $exit_status;;
    esac
}

Если вы используете zsh, убедитесь, что setopt promptsubstв вашем файле .zshrc.

Если вы используете bash, добавьте:

PROMPT_COMMAND=precmd
trap preexec DEBUG

но на самом деле вам следует использовать более сложную ловушку DEBUG, упомянутую вhttps://superuser.com/a/175802/15334

Другой вариант — это setopt printexitvalueдостаточно близко к тому, что вам нужно.

решение2

Надеюсь, этот вопрос все еще будет интересовать людей в 2019 году...

130довольно редкий статус завершения (я полагаю, что UNIX в том виде, в котором он был реализован в первые дни, распознавал статусы завершения только до 128) — так что просто игнорируйте его.

# pseudocode

if exit_status == 0 then
    do nothing
else
    if exit_status == 130 then
        do nothing
    else
        print " [red]exit_status[/red]"

На zshязыке оригинала это означает:

%(0?..%(130?.. %F{red}%?%f))

Обновлять:вы написали, что zshустанавливает код выхода на 1и Ctrl-Cна bash. 130Здесь, в 2019 году, оба bashи zshвозвращают 130.

Связанный контент