Home  >  Article  >  Web Front-end  >  Detailed explanation of how nodejs prints highlighted code on the console

Detailed explanation of how nodejs prints highlighted code on the console

青灯夜游
青灯夜游forward
2021-05-12 10:46:282569browse

This article will introduce to you how nodejs prints highlighted code on the console. It has certain reference value. Friends in need can refer to it. I hope it will be helpful to everyone.

Detailed explanation of how nodejs prints highlighted code on the console

When the code runs and an error is reported, we will print the error. There is stack information in the error, and the corresponding code location can be located. But sometimes we hope to print the code of the error location more directly and accurately. [Recommended learning: "nodejs Tutorial"]

For example:

Detailed explanation of how nodejs prints highlighted code on the console

This can be done using @babel/code-frames To:

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

Do you feel that it is more magical? How does it print out the above code format (code frame)?

In this article, we will explore the principle.

Will mainly answer three questions:

  • How to print out the code frame that marks the code at the corresponding position (the printing format in the picture above)
  • How to achieve high syntax Bright
  • How to print colors on the console

How to print code frame

Let’s ignore the highlighting first and achieve printing in this format:

Detailed explanation of how nodejs prints highlighted code on the console

Do you have any ideas?

In fact, it is easier to think of it. If the source code and the row and column numbers of the beginning and end of the mark are passed in, then we can calculate which lines display the markers and which columns of these lines, and then Each line of code is processed in turn. If there is no mark in this line, it will remain as it is. If there is a mark in this line, then a marker ">" will be printed at the beginning, and a line of marker ## will be printed below. #"^", the last marked line also prints an error message.

Let’s take a look at the implementation of @babel/code-frame:

First, split the string into an array for each line, and then calculate the location of the marker based on the passed in position Location.

For example, columns 1 to 12 in the second row and columns 0 to 5 in the third row in the picture.

Detailed explanation of how nodejs prints highlighted code on the console

Then process each line. If there is a mark in this line, spell it into the format of marker gutter (line number) code, and print a line of marker below. The last marker line prints the message. No tags are processed.

Detailed explanation of how nodejs prints highlighted code on the console

The final result is this code frame:

Detailed explanation of how nodejs prints highlighted code on the console

We have implemented the code frame Splicing, highlighting is temporarily ignored, so how to do syntax highlighting?

How to implement syntax highlighting

Achieving syntax highlighting requires understanding the code, but if it is just highlighting, lexical analysis is enough. Babel does the same thing. The logic of highlighting code is completed in the @babel/highlight package.

Look at the effect first:

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

The above source code is divided into token arrays:

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

How is the token divided?

Generally speaking, lexical analysis is a finite state automaton (DFA), but the implementation here is relatively simple, through regular matching:

js-tokens This package exposes a regular and a function , the regular expression is used to identify tokens, which have many groups, and the function returns different types for different group subscripts, so that token identification and classification can be completed.

Detailed explanation of how nodejs prints highlighted code on the console

is also used in the @babel/highlight package:

Detailed explanation of how nodejs prints highlighted code on the console

(There are many regular expressions for lexical analysis Restrictions, such as the inability to handle recursion, so this method is not universal. General lexical analysis still has to use state machine DFA.)

After classification, different tokens display different colors, just create a map .

@babel/highlight does the same thing:

Detailed explanation of how nodejs prints highlighted code on the console

We know how to do syntax highlighting, and use the chalk api to print colors, then control What is the principle of Taiwan printing color?

如何在控制台打印颜色

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

格式是这样的:

Detailed explanation of how nodejs prints highlighted code on the console

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

我们来试一下:

Detailed explanation of how nodejs prints highlighted code on the console

都打印了正确的样式!

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

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

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

1Detailed explanation of how nodejs prints highlighted code on the console

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

总结

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

1Detailed explanation of how nodejs prints highlighted code on the console

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

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

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

The above is the detailed content of Detailed explanation of how nodejs prints highlighted code on the console. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:juejin.cn. If there is any infringement, please contact admin@php.cn delete