PS1 で echo -e を使用すると、シェルで改行の問題が発生する

PS1 で echo -e を使用すると、シェルで改行の問題が発生する

問題:

コマンドラインプロンプトを開きます:

ここに画像の説明を入力してください

文字 a を複数回入力します:

ここに画像の説明を入力してください

新しい行に折り返される代わりに、入力されたテキストは同じ行に折り返されます。

ここに画像の説明を入力してください

ここで、b キーを押します。2 回目に行の折り返しが必要になった場合は、新しい行に折り返されます。

ここに画像の説明を入力してください


この動作の原因は何ですか?

このように PS1 を使用すると、次のような動作が発生します。

ps1Color="\033[1;35m"
export PS1='$(echo -en $ps1Color) Baz $'

色を直接使用するのではなくechoを使用する理由は、前のコマンドの終了ステータスに基づいて条件付きで色を追加したいためです。

色を直接使用しても、この動作は発生しません。


私の質問は次のとおりです:

  • PS1で使用するカラーコードを印刷するにはどうすればいいですか?エコーを使用する?
  • PS1 を条件付きで別の色に変更したい場合、これを行う最善の方法は何ですか?
  • なぜこのような動作が見られるのでしょうか?

アップデート

はっきり言って、私は色を変えたいのでエコーを使ってこれをやりたいのです条件付きで

私が現在持っているものは次のとおりです:

function setPs1Colors_start () {

    local previousExit=$?

    local ps1Color="\033[1;35m"
    local ps1FailBackground="\e[41m"

    echo -en $ps1Color

    if [[ previousExit -ne 0 ]]
    then
        echo -en $ps1FailBackground
    fi

}

function setPs1Colors_end () {
    local ps1DefaultColor="\033[0m"
    echo -en $ps1DefaultColor
}

export PS1='$(setPs1Colors_start)[$(date +%b\-%d\ %k:%M)][$(versionControlInfo)\W]\$$(setPs1Colors_end) '

答え1

\033[1;35m7 文字です。bashこれらの 7 文字が実際には null 幅であるとは推測できません。そうでない場合は、7 列幅であると認識されます。

編集キーを使用しているときにカーソルを移動するためにカーソル位置シーケンス (上、下、左、右) を使用しているため、エディタ (または、readlineエディタが使用する基礎となる行エディタ) は、画面上の現在の位置を知る必要があります。

したがって、プロンプト内のどの文字がカーソルを移動しないかを伝える必要があります。 ではbash、 を使用することでこれが行われ、\[...\]シェルに内部の幅がゼロであることを伝えます。

また、 のプロンプト展開ではESC 文字としてbash認識される\eため、 を使用する必要はありませんecho -e。次のようにすればよいだけです。

PS1='\[\e[1;35m\] blah $ '

echo、またはより良い を使用する必要がある場合はprintf、次のようにします。

PS1='\[$(if ...; then printf "$color1"; fi)\] blah $ '

または:

PS1='$(if ...; then printf "\[$color1\]"; fi) blah $ '

では、のzshに相当するものはの に似ていますが、文字属性を変更するディレクティブがあるため、次のようにします。bash\[...\]%{...%}tcshzsh

PS1='%B%F{magenta}blah $ '

太字マゼンタの前景用。また、 on を含むいくつかの形式の条件テストもある$?ため、redif error, green else は次のように記述できます。

PS1='%F{%(?:green:red%)}blah%f $ '

tcshには があります%Bが、 はありません%F{color}。そこでは、次のように使用します。

set prompt = '%{\e[1;35m%}blah $ '

ksh88またはではpdksh、次のようにします。

PS1=$(printf '\5\r\5\33[1;35m\5blah $ ')

これは文字(ここでは0x5)を逃げる文字です。次に、テキストをそれらのペアで囲むことで、シェルにその文字が表示されないことを伝えます。0x5 以外の文字を使用できますが、プロンプトに表示されてはなりません。また、mksh を除いて、シェルが実際にその文字 (CR 文字と共に) を書き込むため、端末によって無視される文字でなければなりません。

ksh93カーソル位置指定シーケンスは 1 つだけ使用します: BS(カーソルを 1 列左に移動します)。右に移動するには、同じ文字を再描画するだけです。したがって、カーソルの位置を知る必要はなく、入力した各文字の幅だけを知る必要があります。これは、端末が余白で自動的に折り返す限り機能します (したがって、この方法では正しく機能しません)。terminatorたとえば、制御シーケンスを含むプロンプトがある場合の副作用の 1 つは、タブ ストップが適切に配置されないことです。

関連情報