91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

nodejs如何在控制臺打印高亮代碼

發布時間:2021-05-12 11:20:04 來源:億速云 閱讀:156 作者:小新 欄目:web開發

這篇文章主要介紹了nodejs如何在控制臺打印高亮代碼,具有一定借鑒價值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。

當代碼運行報錯時,我們會打印錯誤,錯誤中有堆棧信息,可以定位到對應的代碼位置。但有的時候我們希望能夠更直接準確的打印報錯位置的代碼。

比如這樣:

nodejs如何在控制臺打印高亮代碼

這個可以使用 @babel/code-frames 來做到:

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

const res = codeFrameColumns(code, {
  start: { line: 2, column: 1 },
  end: { line: 3, column: 5 },
}, {
  highlightCode: true,
  message: '這里出錯了'
});

console.log(res);

有沒有感覺比較神奇,它是怎么做到的打印出上面的代碼格式的(code frame)?

本文我們就來探究下原理。

主要會解答三個問題:

  • 如何打印出標記相應位置代碼的 code frame(就是上圖的打印格式)

  • 如何實現語法高亮

  • 如何在控制臺打印顏色

如何打印 code frame

我們先不管高亮,實現這樣的格式的打印:

nodejs如何在控制臺打印高亮代碼

有啥思路沒?

其實也比較容易想到,傳入了源代碼、標記開始和結束的行列號,那么我們就能夠計算出顯示標記(marker)的行是哪些,以及這些行的哪些列,然后依次對每一行代碼做處理,如果本行沒有標記則保持原樣,如果本行有標記的話,那么就在開始打印一個 marker “>”,并且在下面打印一行 marker "^",最后一個標記行還要打印錯誤信息。

我們來看一下 @babel/code-frame 的實現:

首先,分割字符串成每一行的數組,然后根據傳入的位置計算出 marker 所在的位置。

比如圖中第二行的第 1 到 12 列,第三行的 0 到 5 列。

nodejs如何在控制臺打印高亮代碼

然后對每一行做處理,如果本行有標記,則拼成 marker + gutter(行號) + 代碼的格式,下面再打印一行 marker,最后的 marker 行打印 message。沒有標記不處理。

nodejs如何在控制臺打印高亮代碼

這樣最終拼出的就是這樣的 code frame:

nodejs如何在控制臺打印高亮代碼

我們實現了 code frame 的拼接,暫時忽略了高亮,那么怎么做語法高亮呢?

如何實現語法高亮

實現語法高亮需要理解代碼,但是如果只是高亮,詞法分析就足夠了。babel 也是這么做的,@babel/highlight 包里面完成了高亮代碼的邏輯。

先看效果:

const a = 1;
const b = 2;
console.log(a + b);

上面的源碼被分成了 token 數組:

[
  [ 'whitespace', '\n' ], [ 'keyword', 'const' ],
  [ 'whitespace', ' ' ],  [ 'name', 'a' ],
  [ 'whitespace', ' ' ],  [ 'punctuator', '=' ],
  [ 'whitespace', ' ' ],  [ 'number', '1' ],
  [ 'punctuator', ';' ],  [ 'whitespace', '\n' ],
  [ 'keyword', 'const' ], [ 'whitespace', ' ' ],
  [ 'name', 'b' ],        [ 'whitespace', ' ' ],
  [ 'punctuator', '=' ],  [ 'whitespace', ' ' ],
  [ 'number', '2' ],      [ 'punctuator', ';' ],
  [ 'whitespace', '\n' ], [ 'name', 'console' ],
  [ 'punctuator', '.' ],  [ 'name', 'log' ],
  [ 'bracket', '(' ],     [ 'name', 'a' ],
  [ 'whitespace', ' ' ],  [ 'punctuator', '+' ],
  [ 'whitespace', ' ' ],  [ 'name', 'b' ],
  [ 'bracket', ')' ],     [ 'punctuator', ';' ],
  [ 'whitespace', '\n' ]
]

token 怎么分的呢?

一般來說詞法分析就是有限狀態自動機(DFA),但是這里實現比較簡單,是通過正則匹配的:

js-tokens 這個包暴露出來一個正則,一個函數,正則是用來識別 token 的,其中有很多個分組,而函數里面是對不同的分組下標返回了不同的類型,這樣就能完成 token 的識別和分類。

nodejs如何在控制臺打印高亮代碼

在 @babel/highlight 包里也是這樣用的:

nodejs如何在控制臺打印高亮代碼

(正則來做詞法分析有很多限制條件,比如不能處理遞歸的情況,所以這種方式不是通用的,通用詞法分析還是得用狀態機 DFA。)

有了分類之后,不同 token 顯示不同顏色,建立個 map 就行了。

@babel/highlight 也是這么做的:

nodejs如何在控制臺打印高亮代碼

我們知道了怎么做語法高亮,使用 chalk 的 api 就可以打印顏色,那控制臺打印顏色的原理是什么呢?

如何在控制臺打印顏色

控制臺打印的是 ASCII 碼,并不是所有的編碼都對應可見字符,ASCII 碼有一部分字符是對應控制字符的,比如 27 是 ESC,就是我們鍵盤上的 ESC 鍵,是 escape 的縮寫,按下它可以完成一些控制功能,這里我們可以通過打印 ESC 的 ASCII 碼來進入控制打印顏色的狀態。

格式是這樣的:

nodejs如何在控制臺打印高亮代碼

打印一個 ESC 的 ASCII 碼,之后是 [ 代表開始,m 代表結束,中間是用 ; 分隔的 n 個控制字符,可以控制很多樣式,比如前景色、背景色、加粗、下劃線等等。

ESC 的 ASCII 碼是 27,有好幾種寫法:一種是字符表示的 \e ,一種是 16 進制的 \0x1b(27 對應的 16進制),一種是 8 進制的 \033,這三種都表示 ESC。

我們來試驗一下: 1 表示加粗、36 表示前景色為青色、4 表示下劃線,下面三種寫法等價:

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

我們來試一下:

nodejs如何在控制臺打印高亮代碼

都打印了正確的樣式!

當然,加了樣式還要去掉,可以加一個 \e[0m 就可以了(\033[0m,\0x1b[0m 等價)。

chalk(nodejs 的在終端打印顏色的庫)的不同方法就是封裝了這些 ASCII 碼的顏色控制字符。

上面每行代碼被高亮過以后的代碼是:

nodejs如何在控制臺打印高亮代碼

這樣也就實現了不同顏色的打印。

總結

至此,我們能實現開頭的效果了:支持 code frame 的打印,支持語法高亮,能夠打印顏色

nodejs如何在控制臺打印高亮代碼

本文我們探究了這種效果的實現原理,先從 code frame 是怎么拼接的,然后每一行的代碼是怎么做高亮的,之后是高亮具體是怎么打印顏色的。

不管是 code frame 的打印,還是語法高亮或者控制臺打印顏色,都是特別常見的功能,希望這篇文章能夠幫你徹底掌握這 3 方面的原理。

感謝你能夠認真閱讀完這篇文章,希望小編分享的“nodejs如何在控制臺打印高亮代碼”這篇文章對大家有幫助,同時也希望大家多多支持億速云,關注億速云行業資訊頻道,更多相關知識等著你來學習!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

鹤壁市| 通城县| 大余县| 常宁市| 温宿县| 江津市| 醴陵市| 徐汇区| 长沙市| 大港区| 蓬安县| 金坛市| 安阳县| 炉霍县| 格尔木市| 全椒县| 耒阳市| 邻水| 临洮县| 麦盖提县| 左权县| 鹰潭市| 义乌市| 安泽县| 土默特右旗| 策勒县| 根河市| 舟曲县| 进贤县| 锡林郭勒盟| 隆林| 湘乡市| 慈溪市| 玛曲县| 曲阜市| 雅安市| 彰武县| 牟定县| 衡水市| 宁德市| 乐山市|