Cet article vous présentera comment nodejs imprime le code en surbrillance sur la console. Il a une certaine valeur de référence. Les amis dans le besoin peuvent s'y référer. J'espère qu'il sera utile à tout le monde.
Lorsque le code s'exécute et qu'une erreur est signalée, nous imprimerons l'erreur. Il y a des informations sur la pile dans l'erreur et l'emplacement du code correspondant peut être localisé. Mais parfois, nous souhaitons pouvoir imprimer le code de l’emplacement de l’erreur de manière plus directe et plus précise. [Apprentissage recommandé : "tutoriel nodejs"]
Par exemple :
Cela peut être fait en utilisant @babel/code-frames Allez sur :
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);
Pensez-vous que c'est plus magique ? Comment imprime-t-il le format de code ci-dessus (cadre de code) ?
Dans cet article, nous allons explorer le principe.
Répondra principalement à trois questions :
Ignorons d'abord la surbrillance et implémentons l'impression dans ce format :
Des idées ?
En fait, il est plus facile d'y penser. Après avoir transmis le code source et les numéros de ligne et de colonne du début et de la fin de la marque, nous pouvons calculer quelles lignes affichent les marqueurs et quelles colonnes de. ces lignes, puis Chaque ligne de code est traitée à tour de rôle. S'il n'y a pas de marque dans cette ligne, elle restera telle quelle. S'il y a une marque dans cette ligne, alors un marqueur “>”
sera imprimé à la place. début, et une ligne de marqueur "^"
sera imprimée en dessous. La dernière ligne marquée sera également imprimée pour imprimer un message d'erreur.
Jetons un coup d'œil à l'implémentation de @babel/code-frame :
Tout d'abord, divisez la chaîne en un tableau pour chaque ligne, puis calculez l'emplacement du marqueur en fonction de l'emplacement de position transmis.
Par exemple, les colonnes 1 à 12 dans la deuxième ligne et les colonnes 0 à 5 dans la troisième ligne de l'image.
Traitez ensuite chaque ligne s'il y a une marque sur cette ligne, épelez-la au format marqueur + gouttière (numéro de ligne) + code, et imprimez-la. une autre ligne sous le marqueur, la dernière ligne du marqueur imprime le message. Aucune balise n'est traitée.
Le cadre de code final est le suivant :
Nous avons implémenté le cadre de code Splicing, la mise en évidence est temporairement ignoré, alors comment faire la coloration syntaxique ?
Réaliser la coloration syntaxique nécessite de comprendre le code, mais s'il s'agit simplement de coloration syntaxique, l'analyse lexicale suffit. Babel fait la même chose. La logique de mise en évidence du code est complétée dans le package @babel/highlight.
Regardez d'abord l'effet :
const a = 1; const b = 2; console.log(a + b);
Le code source ci-dessus est divisé en tableaux de jetons :
[ [ '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' ] ]
Comment le jeton est-il divisé ?
D'une manière générale, l'analyse lexicale est un automate à états finis (DFA), mais la mise en œuvre ici est relativement simple, grâce à une correspondance régulière :
js-tokens Ce paquet expose un régulier et une fonction , l'expression régulière est utilisée pour identifier les jetons, qui ont de nombreux groupes, et la fonction renvoie différents types pour différents indices de groupe, afin que l'identification et la classification des jetons puissent être complétées.
est également utilisé dans le package @babel/highlight :
(Il existe de nombreuses expressions régulières pour l'analyse lexicale Des restrictions, telles que l'incapacité de gérer la récursivité, cette méthode n'est donc pas universelle. L'analyse lexicale générale doit toujours utiliser la machine à états DFA)
Après la classification, différents jetons affichent des couleurs différentes, créez simplement une carte.
@babel/highlight fait également ceci :
Nous savons comment faire la coloration syntaxique et utiliser l'API de craie pour imprimer les couleurs, puis contrôler ce qui est le principe de l'impression couleur à Taiwan ?
控制台打印的是 ASCII 码,并不是所有的编码都对应可见字符,ASCII 码有一部分字符是对应控制字符的,比如 27 是 ESC,就是我们键盘上的 ESC 键,是 escape 的缩写,按下它可以完成一些控制功能,这里我们可以通过打印 ESC 的 ASCII 码来进入控制打印颜色的状态。
格式是这样的:
打印一个 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
我们来试一下:
都打印了正确的样式!
当然,加了样式还要去掉,可以加一个 \e[0m
就可以了(\033[0m
,\0x1b[0m
等价)。
chalk(nodejs 的在终端打印颜色的库)的不同方法就是封装了这些 ASCII 码的颜色控制字符。
上面每行代码被高亮过以后的代码是:
这样也就实现了不同颜色的打印。
至此,我们能实现开头的效果了:支持 code frame 的打印,支持语法高亮,能够打印颜色
本文我们探究了这种效果的实现原理,先从 code frame 是怎么拼接的,然后每一行的代码是怎么做高亮的,之后是高亮具体是怎么打印颜色的。
不管是 code frame 的打印,还是语法高亮或者控制台打印颜色,都是特别常见的功能,希望这篇文章能够帮你彻底掌握这 3 方面的原理。
更多编程相关知识,请访问:编程视频!!
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!