すべての出力が端末に渡されるわけではありません。

すべての出力が端末に渡されるわけではありません。

私が知っている限り、うまく動作するコマンドラインプログラムは$TERM環境変数をチェックし、端末エミュレータの名前を取得し、データベース内の対応する項目を見つけて、これらのterminfoエスケープコードを使用して色、フォントなどの端末設定を制御する必要があります。 、スタイル、ワイプ画面を消去し、カーソル位置を設定します。

しかし、私は怠惰なプログラマーなので、いくつかのテキストを緑にしたい場合は、最も簡単な方法は私のプログラムにANSIエスケープコードを直接挿入することです。

print("\033[32mhi\033[0m")

端末の色をこのように変更するシンプル実装により、新しい依存関係(ncursesなど)を学ぶ必要がなく、外部プログラム(ncursesなど)を実行する必要がなく、ターミナルライブラリを持つ言語ではなく文字列を持つすべての言語tputでプログラムを作成できます。 。

私の理想主義者は、特定の実装よりも標準に頼ることが常に良いと信じています。私のmacOSインストールには、2000を超える端末定義が付属しています/usr/share/terminfo。一方、実用主義者は、誰もが長年にわたってANSIコードを内蔵しており、すべてが大丈夫だと指摘しています。

$TERMヘルパーライブラリを使用せずにANSIコードを直接使用するコードや、それ以外のものですが確認するソフトウェア、dumbまったく確認しないソフトウェアをよく見ます。$TERMこれについて文句を言ったり、他の端末タイプのサポートを求める人はほとんどいません。

それ以外にも、インターネットで本当にたくさんの文章を見て、言及されていない他の端末タイプまたはエスケープコードは、ANSIを「ターミナルで太字と色を作成する方法」に設定します。他のすべてのエスケープコードセットは消えたように見え、ANSIコード(またはECMA-48コードまたはVT102コード)は開発コミュニティで確立された事実上の標準になりました。

だから私の質問は:2019年にコマンドラインソフトウェアを書いた場合、ANSIを使用する端末でのみ使用されると仮定しても安全ですか?


編集する:人々は、tputterminfoを処理することなく、画面に色を印刷するために実行時にそれを呼び出すことを提案します。これは効果的で多くの場合に良い解決策ですが、私の考えでは、プログラムの起動時に別々のバイナリを複数回実行する必要があるため、不要なランタイムコストが発生します。

ベストアンサー1

質問を正しく理解すると、実際にコメントが出ますか?考えてみるべきいくつかの点をまとめてみましょう。

すべての出力が端末に渡されるわけではありません。

ちょっと聞こえますが、世界のすべての端末がANSIシーケンスを正しく理解していても(次の説明のコメントで述べたものとは異なります)みんな反例を探すだけでも文を拒否できます。grep出力がファイルや他のプログラム(インタラクティブな使用やスクリプトプログラムの呼び出しなど)を介してリダイレクトされる2つのケースを考えてみましょう。

このような場合、通常は次のような出力が必要です。いいえ取り扱いを簡素化するために色を付けた。この場合、環境変数にのみ依存するだけではTERM不十分です。たとえば、パイプラインをインタラクティブに入力することができ、これにより設定されたがTERM望ましくないカラー出力が発生します。

色は異なる場合があります

私は生のANSIシーケンスを独自に出力するスクリプトをかなりたくさん書いていますTERM(通常は色をオンまたはオフにするオプションを含みます)。異なるターミナルエミュレータ、シェル、または同じターミナルエミュレータのオプションを使用すると、異なる色で出力されることがよくあります。まれに(しかし、最新のLinuxシステムに存在し、見つけることができます)認識範囲外の色(黒い背景に暗い灰色など)もあります。時々緑でなければならないことにも「線が引かれた」効果が適用されることがあります。

「興味深い洞察」を得るには、多くのANSIエスケープシーケンスを使用するすべてのテストと無条件(つまり独立して)次のことを行い、TERM最後rxvtgnome-terminalLinuxxtermコンソールで実行します。

抽象化レイヤーの1つを使用しないと、ターゲットアプリケーションがエスケープシーケンスを認識して処理できるとしても、色付けが失敗する可能性が常にあります。

結論として

2019年には、生のANSIエスケープシーケンスが期待どおりに機能すると仮定することは完全に安全ではありません。

アプリケーションの端末制御がどれほど重要かを考えてみましょう。重要な場合(カラー/ターミナル制御がないと重要な機能が失われるという点で)、元のANSIエスケープシーケンスに問題があることです。リスクが高すぎます。それほど重要ではない場合(たとえば、目を引くログ、カラフルなインタラクティブメニューとシンプルなインタラクティブメニューなど)、カラー出力に非常に制限された抽象化(例:raw ANSIシーケンス+すべてオフにするオプション)を使用することは合理的です。色))。

その他の相対化ステートメント

カラー出力やその他の端末制御シーケンスが必要な同じアプリケーションも取得する必要がある場合入力する特別な方法として、ncursesやもう少し「現代的な」ソリューションなど、徹底的に開発されたソリューションを見つける必要があります。

コメントで指摘したように、テストされた環境だけがすべてのソフトウェアに対して本当に安全です。環境を理解したら、いつでも(いくつかの抽象的な「移植性」を犠牲にしても)、その環境で実装されているプログラムに仮定を追加できます。

最後に、プログラムははい実際には、端末情報を含む高レベルライブラリを使用することはすべての場合に安全ではありません。色は設定された端末のカラースキームによって異なり、一部の効果(下線など)はすべての端末とフォントの組み合わせでは機能しません。その後、TERM「間違った」設定によってアプリケーションが失敗することがあります(tmuxしばしば実行の問題が発生しますssh)。

おすすめ記事