Heim  >  Artikel  >  Web-Frontend  >  Detaillierte Erklärung, wie NodeJS hervorgehobenen Code auf der Konsole druckt

Detaillierte Erklärung, wie NodeJS hervorgehobenen Code auf der Konsole druckt

青灯夜游
青灯夜游nach vorne
2021-05-12 10:46:282580Durchsuche

In diesem Artikel erfahren Sie, wie NodeJS hervorgehobenen Code auf der Konsole druckt. Es hat einen gewissen Referenzwert. Freunde in Not können sich darauf beziehen. Ich hoffe, es wird für alle hilfreich sein.

Detaillierte Erklärung, wie NodeJS hervorgehobenen Code auf der Konsole druckt

Wenn der Code ausgeführt wird und ein Fehler gemeldet wird, drucken wir den Fehler aus. Der Fehler enthält Stapelinformationen und der entsprechende Codespeicherort kann gefunden werden. Aber manchmal möchten wir den Code des Fehlerorts direkter und genauer drucken können. [Empfohlenes Lernen: „nodejs-Tutorial“]

Zum Beispiel:

Detaillierte Erklärung, wie NodeJS hervorgehobenen Code auf der Konsole druckt

Dies kann mit @babel/code-frames erfolgen:

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);

Fühlst du dich magischer, wie geht das? Drucken Was ist der Coderahmen des obigen Codes?

In diesem Artikel gehen wir auf das Prinzip ein.

Beantwortet hauptsächlich drei Fragen:

  • Wie drucke ich den Coderahmen aus, der den entsprechenden Positionscode markiert (das Druckformat im Bild oben)?
  • Wie implementiert man Syntaxhervorhebung?
  • Wie drucke ich Farben auf der Konsole

So drucken Sie einen Coderahmen

Lassen Sie uns zunächst die Hervorhebung ignorieren und das Drucken in diesem Format implementieren:

Detaillierte Erklärung, wie NodeJS hervorgehobenen Code auf der Konsole druckt

Irgendwelche Ideen?

Tatsächlich ist es einfacher, darüber nachzudenken, wenn der Quellcode sowie die Zeilen- und Spaltennummern am Anfang und Ende der Markierung übergeben werden, dann können wir berechnen, welche Zeilen Markierungen (Markierungen) und welche Spalten davon anzeigen Diese Zeilen werden dann nacheinander verarbeitet. Wenn in dieser Zeile keine Markierung vorhanden ist, bleibt sie unverändert. Wenn in dieser Zeile eine Markierung vorhanden ist, wird sie am Anfang gedruckt “>”,并且在下面打印一行 marker "^", und in der letzten markierten Zeile wird eine Fehlermeldung gedruckt.

Werfen wir einen Blick auf die Implementierung von @babel/code-frame:

Teilen Sie zunächst die Zeichenfolge für jede Zeile in ein Array auf und berechnen Sie dann die Position des Markers basierend auf der übergebenen Position.

Zum Beispiel die Spalten 1 bis 12 in der zweiten Zeile und die Spalten 0 bis 5 in der dritten Zeile im Bild.

Detaillierte Erklärung, wie NodeJS hervorgehobenen Code auf der Konsole druckt

Verarbeiten Sie dann jede Zeile, wenn sich in dieser Zeile eine Markierung befindet, diese im Format Markierung + Zwischensteg (Zeilennummer) + Code. Drucken Sie anschließend eine Markierungszeile und die letzte Markierungszeile wird eine Nachricht drucken. Es werden keine Tags verarbeitet.

Detaillierte Erklärung, wie NodeJS hervorgehobenen Code auf der Konsole druckt

Der letzte Coderahmen ist dieser:

Detaillierte Erklärung, wie NodeJS hervorgehobenen Code auf der Konsole druckt

Wir haben das Spleißen von Coderahmen implementiert und die Hervorhebung vorerst ignoriert. Wie führen wir also die Syntaxhervorhebung durch?

So implementieren Sie die Syntaxhervorhebung

Um die Syntaxhervorhebung zu erreichen, müssen Sie den Code verstehen. Wenn es sich jedoch nur um eine Hervorhebung handelt, reicht eine lexikalische Analyse aus. Babel macht das Gleiche. Die Logik zum Hervorheben von Code wird im Paket @babel/highlight vervollständigt.

Schauen wir uns zunächst den Effekt an:

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

Der obige Quellcode ist in Token-Arrays unterteilt:

[
  [ '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' ]
]

Wie ist der Token aufgeteilt?

Im Allgemeinen handelt es sich bei der lexikalischen Analyse um einen Finite-State-Automaten (DFA), aber die Implementierung hier ist durch regulären Abgleich relativ einfach:

js-tokens Dieses Paket stellt einen regulären Ausdruck und eine Funktion bereit, und der reguläre Ausdruck wird verwendet Identifizieren Sie Token. Es gibt viele Gruppen und die Funktion gibt unterschiedliche Typen für verschiedene Gruppenindizes zurück, sodass die Token-Identifizierung und -Klassifizierung abgeschlossen werden kann.

Detaillierte Erklärung, wie NodeJS hervorgehobenen Code auf der Konsole druckt

wird auch im @babel/highlight-Paket verwendet:

Detaillierte Erklärung, wie NodeJS hervorgehobenen Code auf der Konsole druckt

(Es gibt viele Einschränkungen bei der regulären lexikalischen Analyse, z. B. die Unfähigkeit, Rekursion zu verarbeiten, daher ist diese Methode keine universelle, universelle lexikalische Analyse erfordert weiterhin die Verwendung der Zustandsmaschine DFA.)

Nach der Klassifizierung zeigen verschiedene Token unterschiedliche Farben an und erstellen einfach eine Karte.

@babel/highlight macht das auch:

Detaillierte Erklärung, wie NodeJS hervorgehobenen Code auf der Konsole druckt

Wir wissen, wie man Syntaxhervorhebung durchführt und die Kreide-API zum Drucken von Farben verwendet. Was ist also das Prinzip des Druckens von Farben auf der Konsole?

如何在控制台打印颜色

控制台打印的是 ASCII 码,并不是所有的编码都对应可见字符,ASCII 码有一部分字符是对应控制字符的,比如 27 是 ESC,就是我们键盘上的 ESC 键,是 escape 的缩写,按下它可以完成一些控制功能,这里我们可以通过打印 ESC 的 ASCII 码来进入控制打印颜色的状态。

格式是这样的:

Detaillierte Erklärung, wie NodeJS hervorgehobenen Code auf der Konsole druckt

打印一个 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

我们来试一下:

Detaillierte Erklärung, wie NodeJS hervorgehobenen Code auf der Konsole druckt

都打印了正确的样式!

当然,加了样式还要去掉,可以加一个 \e[0m 就可以了(\033[0m,\0x1b[0m 等价)。

chalk(nodejs 的在终端打印颜色的库)的不同方法就是封装了这些 ASCII 码的颜色控制字符。

上面每行代码被高亮过以后的代码是:

1Detaillierte Erklärung, wie NodeJS hervorgehobenen Code auf der Konsole druckt

这样也就实现了不同颜色的打印。

总结

至此,我们能实现开头的效果了:支持 code frame 的打印,支持语法高亮,能够打印颜色

1Detaillierte Erklärung, wie NodeJS hervorgehobenen Code auf der Konsole druckt

本文我们探究了这种效果的实现原理,先从 code frame 是怎么拼接的,然后每一行的代码是怎么做高亮的,之后是高亮具体是怎么打印颜色的。

不管是 code frame 的打印,还是语法高亮或者控制台打印颜色,都是特别常见的功能,希望这篇文章能够帮你彻底掌握这 3 方面的原理。

更多编程相关知识,请访问:编程视频!!

Das obige ist der detaillierte Inhalt vonDetaillierte Erklärung, wie NodeJS hervorgehobenen Code auf der Konsole druckt. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:juejin.cn. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen