最後のコマンド終了コードを bash プロンプトに設定

最後のコマンド終了コードを bash プロンプトに設定

私はUbuntu 18.04を実行しており、次のようにbashプロンプトを設定したいと思います。

user:~/Documents [14:22:07] 1 $

私のPS1は次のとおりです

ALERT_COLOR="$(tput setaf 1)"

# Display unsuccessful exit codes
function exit_status {
    last_status=$?
    if [[ $last_status != 0 ]]; then
        echo "$ALERT_COLOR[$last_status]"
    fi  
}

parse_git_branch() {
 git branch 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/(\1)/'
}
if [ "$color_prompt" = yes ]; then
 PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u:\[\033[01;34m\]\w\[\033[01;31m\]$(parse_git_branch)\[\033[00m\] \[\033[36m\][\t] \[$ALERT_COLOR\]$exit_status \[\033[0;37m\]\$ '
else
 PS1='${debian_chroot:+($debian_chroot)}\u:\w$(parse_git_branch)\$ '
fi
unset color_prompt force_color_prompt

終了コードを除いて、すべてがうまく機能します。終了コードは表示されません。$?PS1でこれを行うと、常に表示されます。0

答え1

問題はここにあります:

PS1='...\[$ALERT_COLOR\]$exit_status ...\$ '
                        ^^

これはパラメータ拡張であるため、設定した関数は呼び出されません。たとえば$(exit_status)、fromなどのコマンド置換から関数を呼び出す必要がありますPROMPT_COMMAND。これは脱出に注意してください\[ .. \]。 Bashはこれを解釈します。今後プロンプトは別の拡張であるため、プロンプト文字列にハードコードする必要があります(プロンプトで拡張変数やその他の項目の一部にすることはできません)。

変数を拡張せずに素早く逃げることがあなたに逆さまに見える場合、私はあなたを責めることはできません。しかし、このように記録されています。:

また、次の表では、プロンプト変数に表示される特殊文字について説明しますPS1PS4[...] 文字列をデコードした後、パラメータ拡張、コマンド置換による拡張、[...]

次のように動作する必要があります。

normal_color=$'\033[00m'
red_color=$'\033[41m'
exit_color=$normal_color

set_exit_color() {
    if [ "$?" != 0 ]; then
        exit_color=$red_color
    else
        exit_color=$normal_color
    fi
}

PROMPT_COMMAND=set_exit_color
PS1='\[$exit_color\][$?]\[$normal_color\] \w\$ '

終了状態を維持するには一時変数が必要だと思いましたが、明らかにプロンプ​​トで拡張された値は変更PROMPT_COMMANDされません。$?プロンプト文字列内でコマンド置換を使用して関数を呼び出す場合は、コマンド置換の終了コードが適用されるため、回避策が必要です。このような:

normal_color=$'\033[00m'
red_color=$'\033[41m'
exit_color=$normal_color

exit_color() {
    exit_code=$?
    if [ "$exit_code" != 0 ]; then
        echo "$red_color"
    else
        echo "$normal_color"
    fi
    return "$exit_code"
}

PS1='\[$(exit_color)\][$?]\[$normal_color\] \w\$ '

コマンドの置換によって引き起こされるサブシェル分岐を保存するためにwithバージョンを使用しますPROMPT_COMMANDが、実際にはほとんど効果がありません。

答え2

私は3行のプロンプトが欲しいので、次のようにします。

۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰ bash ۰۰ 10:56:52
jackman@jackmanVM:~/tmp
+$ cat ~/.bash_prompt
# ... some other stuff ...

__bash_prompt() {
    local last_status=$1
    local cwd=$( sed "s,^$HOME,~," <<<"$PWD" )
    local user_host_path="${debian_chroot:+($debian_chroot) }$(id -un)@$(hostname -s):$cwd"

    # terminal title
    echo -ne "\e]0;$user_host_path\a"

    # separator and date
    local char="۰"
    printf "%s bash %s " "$(jot -s "" -b "$char" $(( $(tput cols) - 18 )) )" "$char$char"
    date '+%T'

    if ((last_status != 0)); then
        local color_bold='\e[0;1m'
        local color_reset='\e[0m'
        printf "$color_bold[%d]$color_reset " $last_status
    fi

    # user@host, directory, git branch
    printf "%s%s\n" "${user_host_path}$(git_current_branch " (%s)")"
}

# ref: https://stackoverflow.com/questions/1039713/different-bash-prompt-for-different-vi-editing-mode
# a single-line PS1 allows the show-mode-in-prompt inputrc setting to be useful
PROMPT_COMMAND='__bash_prompt $?'
PS1='\$ '

~/.bashrcからファイルを取得します。

終了ステータスは次のように表示されます

۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰ bash ۰۰ 11:05:10
jackman@jackmanVM:~/tmp
+$ sh -c 'exit 42'
۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰ bash ۰۰ 11:05:14
[42] jackman@jackmanVM:~/tmp
+$ false
۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰ bash ۰۰ 11:05:16
[1] jackman@jackmanVM:~/tmp
+$ true
۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰ bash ۰۰ 11:05:17
jackman@jackmanVM:~/tmp
+$ 

関数で最初にすることは、他のコマンドを実行する前に最後の終了状態を保存することです。

私はPROMPT_COMMANDを使ってすべての素晴らしいものを出力し、viモードを使用してviモードインジケータを見るのが好きなので、単純なPS1しか持っていません。私もこれを持っています:

۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰ bash ۰۰ 10:57:21
jackman@jackmanVM:~/tmp
+$ cat ~/.inputrc
set editing-mode vi

set show-mode-in-prompt on
$if Bash
    # not until bash 4.4, I believe
    # escape sequences: https://stackoverflow.com/a/42107711/7552 
    #set vi-ins-mode-string "+\1\e[5 q\2"
    #set vi-cmd-mode-string ":\1\e[1 q\2"
    set vi-ins-mode-string +
    set vi-cmd-mode-string :
$endif

私は使うログインシェルとして使用し、時にはkshに使用するため、プロンプト区切り文字にシェル名を入れて、入力している内容を追跡できます。

関連情報