行の長さの計算を中断せずにBashのPS1にコマンドを含める方法


13

Tonin は、デフォルトのプロンプトでバグ指摘しました。最小限の例:

  1. PS1を設定します。

    PS1='$(exit_code=$?; [[ $exit_code -eq 0 ]] || printf %s $(tput setaf 1) $exit_code $(tput sgr0) " ")$ '

    この時点で、プロンプトは次のようになります。

    $ 
  2. 次を実行して、終了コードの出力をトリガーします。

    false

    これで、プロンプトの行頭に赤の終了コードが含まれます。

    1 $ 
  3. Ctrl-を押しrます。
  4. 「false」と入力します。これで、プロンプトには検索のみが含まれます。

    (reverse-i-search)`false': false
  5. を押しEnterます。

結果の端末履歴には、次が含まれます。

1 $ch)`false': false

期待される出力:

1 $ false

つまり、履歴検索の出力がプロンプトと混合され、実行された実際のコマンドが隠されているようです。

私はこれを回避するために使用してみましたPROMPT_COMMAND

set_exit_code() {
    exit_code=$?
    [[ $exit_code -eq 0 ]] || printf %s $(tput setaf 1) $exit_code $(tput sgr0) " "
}
set_bash_prompt() {
    PS1='$(set_exit_code)$ ' # Double quotes give the same result
}
PROMPT_COMMAND=set_bash_prompt

これは機能していないようです-行は検索して実行した後と以前とまったく同じに見えます。

どうすれば修正できますか?


1
a

回答:


8

askubuntu.comで答えを見つけました。@qeirhaは、bashにプロンプ​​トの長さで文字のシーケンスをカウントすべきでないことを伝えなければならないと述べ、それをで囲むことによってそれを行い\[ \]ます。提供された例に基づいて、1つのソリューションを次に示します。

red=$(tput setaf 1)

reset=$(tput sgr0)

[ "$PS1" = "\\s-\\v\\\$ " ] && PS1='$(exit_code=$?; [[ $exit_code -eq 0 ]] || printf %s \[$red\] $exit_code \[$reset\] " ")$ '

Ubuntu尋ねる必要はありません。ここでもこの質問に対する十分な回答があります。
マナトワーク

@manatworkのアドバイスをありがとう!私は説明に適切なクレジットを与えたいと思い、参考として参考文献を提供しました。
ティモシーマーティン

クレジットを与えることは問題ではありません。しかし、問題について話している間、エスケープされていないバックスラッシュはMarkdownから消えていたので、あなたの普通の\ [はあなたの投稿で[になりました。これは、インラインコードまたはコードブロックマークアップを使用することで回避できます。(MarkdownまたはHTMLを使用して投稿をフォーマットするにはどうすればよいですか?
manatwork

1
ど!他のPS1コードでも同じ問題を既に修正しましたが、なぜそれが表示されないのですか?
l0b0

1
PS1='$(exit_code=$?; [[ $exit_code -eq 0 ]] || printf %s \[$(tput setaf 1)\] $exit_code \[$(tput sgr0)\] " ")$ '

(申し訳ありませんが、ここでは何の説明は参照しない適切PS1をカスタマイズする方法は?またはプロンプトの長さの計算問題やに関するその他の質問\[... \]。)


2番目の@ l0b0の質問に、PS1を使用して追加し\[...\]、プロンプトを生成するすべてのコードを単一の文字列に入れることができる限り正常に動作します。ただし、コードを小さな関数に分割する場合は、同じ文字列/関数に開始ブラケットと終了ブラケットを配置できないところまで来ます。そして、それは改行を壊します。各プロンプトでPROMPT_COMMAND再計算に使用することに頼らない限りPS1
トニン

1

@manatworkの回答を拡張しますがPS1、異なる関数で計算を分割するコードを保持する場合、次の方法でプロンプトを記述できます。

set_exit_code() {
    exit_code=$?
    [[ $exit_code -eq 0 ]] || printf "\[$(tput setaf 1)\] $exit_code \[$(tput sgr0)\] "
}
set_bash_prompt() {
    PS1="$(set_exit_code)$ " # with double quotes!
}
PROMPT_COMMAND=set_bash_prompt

関数で設定するPS1ときと使用printfするときの両方で、二重引用符は必須です。


将来の参照のために、bash関数を使用してください.bashrc-コードを別のファイルに入れてそれを呼び出さないでください。
starbeamrainbowlabs
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.