Node.js コンソールで強調表示されたコードを印刷する方法

Node.js コンソールで強調表示されたコードを印刷する方法

序文

コードを実行してエラーが発生すると、エラーが出力されます。エラーにはスタック情報が含まれており、これを使用して対応するコードの場所を見つけることができます。しかし、エラー箇所のコードをより直接的かつ正確に印刷したい場合もあります。例えば:

これは @babel/code-frames を使用して実行できます。

const { codeFrameColumns } = require('@babel/code-frame');

const res = codeFrameColumns(コード, {
  開始: { 行: 2, 列: 1 },
  終了: { 行: 3、列: 5 },
}, {
  ハイライトコード: true、
  メッセージ: 「ここで問題が発生しました」
});

コンソールログ(res);

魔法のように感じますか? 上記のコード形式 (コード フレーム) をどのように印刷するのでしょうか?

この記事では、その原則について説明します。

以下の 3 つの主な質問に答えます。

  • 対応する位置コードをマークするコードフレームの印刷方法(上図の印刷形式)
  • 構文強調表示を実装する方法
  • コンソールで色を印刷する方法

コードフレームを印刷する方法

ハイライトを無視して、次の形式で印刷してみましょう。

何かアイデアはありますか?

実際、考えるのは比較的簡単です。ソース コードと、マークの開始と終了の行番号と列番号を渡した後、どの行と列にマーカーが表示されるかを計算し、各コード行を順番に処理します。この行にマーカーがない場合は、そのままにします。この行にマーカーがある場合は、先頭にマーカー ">" を印刷し、その下にマーカー "^" の行を印刷します。最後のマーカー行には、エラー メッセージも印刷されます。

@babel/code-frame の実装を見てみましょう。

まず、文字列を行ごとに配列に分割し、渡された位置に基づいてマーカーの位置を計算します。

たとえば、2 行目には列 1 ~ 12、3 行目には列 0 ~ 5 です。

次に各行を処理します。この行にマークがある場合は、マーカー + ガター (行番号) + コードの形式で綴られます。次に別のマーカー行を印刷し、最後のマーカー行にメッセージを印刷します。マークなしは処理されません。

最終的なコードフレームは次のようになります。

コード フレームのスプライシングを実装し、ハイライトを一時的に無視しました。では、構文のハイライトはどのように行うのでしょうか?

構文強調表示を実装する方法

構文の強調表示を実装するにはコードを理解する必要がありますが、強調表示だけであれば、字句解析で十分です。 Babel も同じことを行います。@babel/highlight パッケージは、コードを強調表示するロジックを実装します。

まず効果を見てみましょう:

定数a = 1;
定数b = 2;
コンソールにログ出力します。

上記のソース コードはトークン配列に分割されています。

[
[ '空白', '\n' ], [ 'キーワード', 'const' ],
[ '空白', ' ' ], [ '名前', 'a' ],
[ '空白', ' ' ], [ '句読点', '=' ],
[ '空白', ' ' ], [ '数字', '1' ],
[ '句読点', ';' ], [ '空白', '\n' ],
[ 'キーワード', 'const' ], [ '空白', ' ' ],
[ '名前', 'b' ], [ '空白', ' ' ],
[ '句読点', '=' ], [ '空白', ' ' ],
[ '数字', '2' ], [ '句読点', ';' ],
[ '空白', '\n' ], [ '名前', 'コンソール' ],
[ '句読点', '.' ], [ '名前', 'ログ' ],
[ '括弧', '(' ], [ '名前', 'a' ],
[ '空白', ' ' ], [ '句読点', '+' ],
[ '空白', ' ' ], [ '名前', 'b' ],
[ '括弧', ')' ], [ '句読点', ';' ],
[ '空白', '\n' ]
]

トークンはどのように分割されますか?

一般的に言えば、字句解析は有限状態オートマトン (DFA) ですが、ここでの実装は規則的なマッチングを通じて比較的単純です。

js-tokens パッケージは、正規表現と関数を公開します。正規表現はトークンを識別するために使用されます。正規表現には多くのグループがあり、関数はグループ添字ごとに異なるタイプを返すため、トークンの識別と分類を完了できます。

これは @babel/highlight パッケージでも使用されます:

(正規表現には、再帰を処理できないなど、字句解析に関する多くの制限があるため、この方法は普遍的ではありません。一般的な字句解析では、依然としてステート マシン (DFA) を使用する必要があります。)

分類が完了すると、異なるトークンが異なる色で表示され、マップを作成できます。

@babel/highlight も同じことを行います:

Chalk の API を使用して構文の強調表示や色の印刷を行う方法はわかっていますが、コンソールで色を印刷する原理は何でしょうか?

コンソールで色を印刷する方法

コンソールは ASCII コードを出力しますが、すべてのコードが可視文字に対応しているわけではありません。ASCII コードの一部の文字は制御文字に対応しています。たとえば、27 は ESC です。これはキーボードの ESC キーで、エスケープの略です。これを押すと、いくつかの制御機能を実行できます。ここで、ESC の ASCII コードを出力することで、印刷色を制御する状態に入ることができます。

形式は次のとおりです。

ESC の ASCII コードを出力し、その後に開始を表す [、終了を表す m、その間に ; で区切られた n 個の制御文字を出力します。これにより、前景色、背景色、太字、下線などの多くのスタイルを制御できます。

ESC の ASCII コードは 27 で、書き方はいくつかあります。1 つは文字表現 \e、1 つは 16 進数の \0x1b (27 に対応する 16 進数)、もう 1 つは 8 進数の \033 です。3 つとも ESC を表します。

試してみましょう: 1 は太字、36 は前景色がシアン、4 は下線を意味します。次の 3 つの書き方は同じです。

\e[36;1;4m
\033[36;1;4分
\0x1b[36;1;4m

試してみましょう:

写真はすべて正しいスタイルで印刷されています。

もちろん、スタイルを追加した後に削除したい場合は、\e[0m を追加できます (\033[0m、\0x1b[0m は同等です)。

chalk (ターミナルで色を印刷するための nodejs ライブラリ) のさまざまな方法は、これらの ASCII カラー制御文字をカプセル化することです。

上記のコードの各行の後のコードが強調表示されています。

これにより、さまざまな色での印刷が可能になります。

要約する

この時点で、当初の効果を実現できます。コードフレームの印刷をサポートし、構文の強調表示をサポートし、カラーで印刷できます。

この記事では、コード フレームの結合方法から始めて、コードの各行を強調表示する方法、強調表示をカラーで印刷する方法まで、この効果の実装原理について説明します。

コード フレームの印刷、構文の強調表示、コンソールの印刷色など、これらはすべて非常に一般的な機能です。この記事が、これら 3 つの側面の原理を徹底的に習得するのに役立つことを願っています。

これで、Node.js コンソールのハイライト印刷コードに関するこの記事は終了です。Node.js コンソールのハイライト印刷に関する関連コンテンツをさらにご覧になりたい場合は、123WORDPRESS.COM の以前の記事を検索するか、以下の関連記事を引き続きご覧ください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。

以下もご興味があるかもしれません:
  • Node とブラウザ コンソールで色付きのテキストを印刷する方法

<<:  CentOS 7でsambaを使用してフォルダーを共有するための完全な手順

>>:  CentOS の MySQL に MariaDB をインストールするときに発生する方法と問題

推薦する

単一のMySQLテーブルを復元する手順

休憩中に、眠気を完全に吹き飛ばす電話がかかってきました。「開発者が更新 SQL を書くときに whe...

MySQL における in と exists の使い方と違いの紹介

まずコードを書いて (int i=0;i<1000;i++){ (int j=0;j<5...

JenkinsのLinuxインストール手順と各種問題解決(ページアクセス初期化パスワード)

1. Java環境jdk1.8を準備するJavaがインストールされているかどうかを確認します。イン...

Docker で ElasticSearch をデプロイする方法

1. ElasticSearch とは何ですか? Elasticsearch も Java で開発さ...

Ubuntu 20.04 に cuda10.1 をインストールする手順 (グラフィック チュートリアル)

インストール前の準備CUDA の主な目的はディープラーニングであり、現在主流のディープラーニングフレ...

一般的な XHTML タグの紹介

<br />しばらくの間、多くの人が XHTML の使い方を知らないことに気付きました。...

Vue+elementを使用してページ上部のタグを実装する方法の詳細な説明

目次1. ページレンダリング2. タグを切り替える3. タグを削除するこのようなタグはどのように記述...

Dockerコンテナでyumを呼び出すときのエラーの解決方法

dockerfile またはコンテナ内で yum を実行すると、エラーが報告され、ソースが見つかりま...

Vue でインデックスをキー属性値として使用することが推奨されないのはなぜですか?

目次序文キーの役割差分アルゴリズムにおけるキーの役割ヘッドノードを同期するテールノードを同期する新し...

CentOS7にMySQL 8.0.26をインストールする手順

1. まず、お使いのマシンに応じて、MySQL 公式サイトから対応するデータベースをダウンロードしま...

Linux カーネル デバイス ドライバー proc ファイル システム ノート

/***************** * proc ファイルシステム***************...

ダイナミッククロックを実現するJS+CSS

この記事の例では、動的な時計を実装するためのJS + CSSの具体的なコードを参考までに共有していま...

Alibaba Cloud Server Ubuntu 設定チュートリアル

Alibaba Cloud のカスタム Ubuntu イメージのインポートには、OSS スナップショ...

MySQLデータベースの操作とメンテナンスのデータ復旧方法

これまでの 3 つの記事では、論理バックアップと物理バックアップを含む、MySQL データベースの一...

複数サーバーの負荷分散を実現するためのNginx構成

Nginx ロード バランシング サーバー: IP: 192.168.0.4 (Nginx-Serv...