シェルで異なる制御文字(^ C、^ D、^ [、…)を表示する方法


13

シェルに制御文字を入力すると、「キャレット表記」と呼ばれるものを使用して表示されます。たとえば、エスケープ^[はキャレット表記のように記述されます。

bashシェルをカスタマイズして、見栄えを良くしたいです。たとえば、私は自分PS1を変えて、PS2色付けされました。私は今、普通のキャラクターと区別しやすくするために、コントロールキャラクターにもユニークな外観を持たせたいと思っています。

$ # Here I type CTRL-C to abort the command.
$ blahblah^C
          ^^ I want these two characters to be displayed differently

シェルで制御文字を異なる方法で強調表示する方法はありますか?

太字で表示することや、通常のテキストとは異なる色で表示することは可能ですか?

ここではbashシェルを使用しbashていますが、多くの異なるシェルに適用される解決策があるため、質問にタグを付けませんでした。

制御文字の強調表示がどのレベルで行われるかわからないことに注意しください。シェル自体にあると最初に思いました。今では、bashのようなシェルでの制御文字の使用方法を制御するのはreadlineであると聞いています。そのため、質問にタグが付けられ、まだ回答を探しています。readline


なぜシェルがそれらを強調していると思いますか?bashそれはreadlineそのようなものを処理するためであり、他のほとんどの場合はttyドライバーです。
mikeserv

知りませんでした。それが私がメモを書いた理由です。他のアプリケーションではviless通常のテキストとは異なる方法で制御文字が強調表示されることが多いため、それは単なる推測でした。この情報を使用して質問を編集します。ありがとうございました!
wefwefa3

それは理にかなっている。その種のものは、シェルにとってより難しいものです。なぜなら、その種のものは2番目の優先事項だからです。エディターの仕事はスクリーン<>ファイルインターフェースを提供することですが、シェルはインタープリター言語のコマンドインタープリターであり、ラインエディターは2番目(またはまったく)ではありません
mikeserv

Readlineのは、他のプログラムによって使用されますが、それはあるのbashの一部:それはそれにリンクされたライブラリです。そして、今日のシェル、特にbashは、考えられるほとんどすべてのことを行います。
アレクシス

そのまま使用するだけで使用できzshます。
ステファンシャゼル

回答:


20

を押すCtrl+Xと、端末エミュレーターはバイト0x18を擬似端末ペアのマスター側に書き込みます。

次に何が起こるかは、tty回線制御(マスター側(エミュレーターの制御下)とスレーブ側(端末で実行中のアプリケーションが対話する)の間にあるカーネル内のソフトウェアモジュール)の構成方法によって異なります。

そのtty回線制御を設定するsttyコマンドがコマンドです。

そのようなダムアプリケーションを実行しているとき、catそのstdinがターミナルであるかどうかを意識せず、気にしません、ターミナルはデフォルトの標準モードにあり、ttyライン制御は粗いラインエディターを実装します。

粗いラインエディタ以上のものを必要とする一部のインタラクティブアプリケーションは、通常、起動時にこれらの設定を変更し、終了時に復元します。現代のシェルは、そのプロンプトでそのようなアプリケーションの例です。独自のより高度なラインエディタを実装します。

通常、コマンドラインを入力している間、シェルはttyラインディシプリンをそのモードにし、Enterキーを押して現在のコマンドを実行すると、シェルは通常のttyモードを復元します(プロンプトを発行する前に有効でした)。

このstty -aコマンドを実行すると、ダムアプリケーションで使用されている現在の設定が表示されます。あなたは見てそうだicanonechoechoctl設定が有効にされています。

それが意味することは:

  • icanon:その粗雑なラインエディタは有効になっています。
  • echo:入力した文字(ターミナルエミュレーターがマスター側に書き込む文字)はエコーバックされます(ターミナルエミュレーターが読み取れるようにします)。
  • echoctl:そのままエコーされる代わりに、制御文字はとしてエコーさ^Xます。

だから、あなたがタイプしA B Backspace-aka-Ctrl+H/? C Ctrl+X Backspace Returnたとしましょう。

端末エミュレータは次を送信しますAB\bC\x18\b\r。回線制御はエコーバックします:AB\b \bC^X\b \b\b \b\r\n、スレーブ側から入力を読み取るアプリケーション(/dev/pts/x)が読み取りますAC\n

アプリケーションが見るのはAC\nのみであり、あなたのプレスがEnterそうである場合にのみ、^Xそこでの出力を制御することができません。

echoの場合、最初の^H^?一部の端末ではerase設定を参照)が\b \b端末に送り返されることに気付くでしょう。これは、カーソルを戻す、スペースで上書きする、カーソルを再び戻すシーケンスであり、2番目の^H結果は\b \b\b \bこれら2つの文字^X文字を消去します。

^X(0x18の)自体に変換されていた^X出力用。のようにB、Backspaceで削除したため、アプリケーションに到達しませんでした。

\r(別名^M)は、エコー用に()、アプリケーション用に\r\n()に変換されました。^M^J\n^J

したがって、これらの愚かなアプリケーションのオプションは何ですか?

  • 無効echostty -echo)。これにより、制御文字のエコー方法が効果的に変わります。何もエコーしません。実際には解決策ではありません。
  • 無効にしechoctlます。これにより、制御文字(^H^M...、およびラインエディタで使用される他のすべて)がエコーされる方法が変更されます。これらはそのままエコーされます。それは、例えば、ESC文字は次のように送信されている\e^[/ 0x1b(端末によるエスケープシーケンスの開始として認識されている)、)バイト^Gあなたが送って\a(あなたの端末のビープ音を作り、BEL)...未オプション。
  • 粗いラインエディターを無効にしstty -icanonます()。粗雑なアプリケーションはずっと使いにくくなるため、実際にはオプションではありません。
  • カーネルコードを編集してttyライン制御の動作を変更し、制御文字のエコーが送信される\e[7m^X\e[mだけではなく^X\e[7m通常、ほとんどの端末でリバースビデオが有効になります)。

オプションrlwrapは、そのようなラッパーを使用して、愚かなアプリケーションに派手なラインエディターを追加するためのダーティハックです。そのラッパーは、事実上read()、端末デバイスからreadline行エディター(tty行規則のモードを変更する)への呼び出しに単純なs を置き換えようとします。

さらに進むと、ターミナルからのすべての入力を乗っ取って、GNUスクリーンの機能に依存するzshのラインエディター(リバースビデオでs を強調表示する)を通過するこのようなソリューションを試すこともできます。^X:exec

独自のラインエディタを実装するアプリケーションの場合、エコーの実行方法を決定するのはアプリケーション次第です。bash制御文字のエコー方法のカスタマイズをサポートしていないreadlineを使用します。

についてはzsh、以下を参照してください。

info --index-search='highlighting, special characters' zsh

zshデフォルトでは印刷できない文字を強調表示します。たとえば、強調表示をカスタマイズできます。

zle_highlight=(special:fg=white,bg=red)

これらの特殊文字の赤の強調表示に白の場合。

ただし、これらの文字のテキスト表現はカスタマイズできません。

UTF-8ロケールで、0x18のは次のようにレンダリングされる^X\u378\U7fffffffとして(二未割り当てのUnicodeコードポイント)を<0378><7FFFFFFF>\u200bとして(不実際に印刷可能なUnicode文字)<200B>

\x80iso8859-1ロケールでは^�...などとしてレンダリングされます。


3

通常、.bashrcファイルにこのコードがあります。

function get_exit_status()
{
        local code=$?
        if [ $code -ne 0 ]
        then
                printf $'\001\033[31m\002'"($code)"$'\001\033[0m\002'" "
        fi
}

そして、PS1でこの関数を呼び出します

PS1='\u@\h \w $(get_exit_status)'

これにより、^ Cを押すとプロンプトに表示されます

I@mycomputer ~ ^C
I@mycomputer ~ (130)

「0」以外のすべての終了ステータスコードが要求されます。


$?PS1の終了ステータスに展開します。例PS1 = '$?\ u @ \ h \ w'
teknopaul
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.