详解nodejs在控制台打印高亮代码的方法

本篇文章给大家介绍一下nodejs如何在控制台打印高亮代码。有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助。

详解nodejs在控制台打印高亮代码的方法

当代码运行报错时,我们会打印错误,错误中有堆栈信息,可以定位到对应的代码位置。但有的时候我们希望能够更直接准确的打印报错位置的代码。【推荐学习:《nodejs 教程》】

比如这样:

1.png

这个可以使用 @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

我们先不管高亮,实现这样的格式的打印:

2.png

有啥思路没?

其实也比较容易想到,传入了源代码、标记开始和结束的行列号,那么我们就能够计算出显示标记(marker)的行是哪些,以及这些行的哪些列,然后依次对每一行代码做处理,如果本行没有标记则保持原样,如果本行有标记的话,那么就在开始打印一个 marker “>”,并且在下面打印一行 marker “^”,最后一个标记行还要打印错误信息。

我们来看一下 @babel/code-frame 的实现:

首先,分割字符串成每一行的数组,然后根据传入的位置计算出 marker 所在的位置。

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

3.png

然后对每一行做处理,如果本行有标记,则拼成 marker + gutter(行号) + 代码的格式,下面再打印一行 marker,最后的 marker 行打印 message。没有标记不处理。

4.png

这样最终拼出的就是这样的 code frame:

5.png

我们实现了 code frame 的拼接,暂时忽略了高亮,那么怎么做语法高亮呢?

如何实现语法高亮

实现语法高亮需要理解代码,但是如果只是高亮,词法分析就足够了。babel 也是这么做的,@babel/highlight 包里面完成了高亮代码的逻辑。

先看效果:

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

登录后复制

上面的源码被分成了 token 数组:

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

登录后复制

token 怎么分的呢?

一般来说词法分析就是有限状态自动机(DFA),但是这里实现比较简单,是通过正则匹配的:

js-tokens 这个包暴露出来一个正则,一个函数,正则是用来识别 token 的,其中有很多个分组,而函数里面是对不同的分组下标返回了不同的类型,这样就能完成 token 的识别和分类。

6.png

在 @babel/highlight 包里也是这样用的:

7.png

(正则来做词法分析有很多限制条件,比如不能处理递归的情况,所以这种方式不是通用的,通用词法分析还是得用状态机 DFA。)

有了分类之后,不同 token 显示不同颜色,建立个 map 就行了。

@babel/highlight 也是这么做的:

8.png

我们知道了怎么做语法高亮,使用 chalk 的 api 就可以打印颜色,那控制台打印颜色的原理是什么呢?

如何在控制台打印颜色

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

格式是这样的:

9.png

打印一个 ESC 的 ASCII 码,之后是 [ 代表开始,m 代表结束,中间是用 ; 分隔的 n 个控制字符,可以控制很多样式,比如前景色、背景色、加粗、下划线等等。

ESC 的 ASCII 码是 27,有好几种写法:一种是字符表示的 e ,一种是 16 进制的 x1b(27 对应的 16进制),一种是 8 进制的 ,这三种都表示 ESC。

我们来试验一下: 1 表示加粗、36 表示前景色为青色、4 表示下划线,下面三种写法等价:

e[36;1;4m[36;1;4mx1b[36;1;4m

登录后复制

我们来试一下:

10.png

都打印了正确的样式!

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

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

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

11.png

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

总结

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

12.png

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

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

更多编程相关知识,请访问:nodejs 教程!!

以上就是详解nodejs在控制台打印高亮代码的方法的详细内容,更多请关注【创想鸟】其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至253000106@qq.com举报,一经查实,本站将立刻删除。

发布者:PHP中文网,转转请注明出处:https://www.chuangxiangniao.com/p/2713251.html

(0)
上一篇 2025年3月7日 21:21:38
下一篇 2025年3月7日 21:21:51

AD推荐 黄金广告位招租... 更多推荐

相关推荐

  • 详解Nodejs Buffer模块的常用API

    本篇文章带大家详细介绍一下nodejs buffer模块的常用api。有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助。 模块概览 Buffer是node的核心模块,开发者可以利用它来处理二进制数据,比如文件流的读写、网络请求…

    2025年3月7日
    200
  • Nodejs中使用string_decoder模块将buffer转成string

    本篇文章给大家介绍一下nodejs中使用string_decoder模块将buffer转成string的方法。有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助。 模块简介 string_decoder模块用于将Buffer转成…

    2025年3月7日
    200
  • nodejs设置NODE_ENV时发生错误怎么解决?

    本篇文章给大家介绍一下windows环境中nodejs设置node_env错误的解决方案。有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助。 【推荐学习:《nodejs》】 今天在看node文档的时候,看到《Node.js 开…

    2025年3月7日 编程技术
    200
  • 详解Nodejs中的阻塞和非阻塞

    本篇文章带大家理解一下nodejs中的阻塞和非阻塞。有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助。 推荐学习:《nodejs》 对于阻塞和非阻塞这两个概念大家应该都有一些自己的理解: 再简单说一下,阻塞大部分是由于同步模式…

    2025年3月7日
    200
  • 如何使用Nodejs连接Mysql,实现基本的增删改查操作

    本篇文章给大家介绍一下如何使用nodejs连接mysql,实现基本的增删改查(crud)操作。有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助。 【推荐学习:《nodejs》】 接下来示例代码的主要技术点包括 基础框架 Koa…

    2025年3月7日 编程技术
    200
  • 深入了解调试nodejs程序的方法

    对于开发者来说,在开发应用程序的过程中,往往为了开发方便和解决bug需要借助于编程语言的调试功能。一般来说我们需要借助于强大IDE的调试功能来完成这项工作。nodejs也不例外。 今天我们来详细介绍一下如何调试nodejs程序。 开启nod…

    2025年3月7日 编程技术
    200
  • 浅谈浏览器中本地运行Node.js的方法

    本篇文章给大家介绍一下在浏览器中本地运行node.js的方法。有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助。 【推荐学习:《nodejs 教程》】 一切要从收到一封邮件开始 大早上,我收到一封邮件,StackBlitz说正…

    2025年3月7日 编程技术
    200
  • 一起了解Nodejs和命令行程序

    本篇文章给大家介绍一下nodejs和命令行程序。有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助。 造物无言却有情,每于寒尽觉春生。千红万紫安排著,只待新雷第一声。 —— 清.张维屏 《新雷》 源起 植根于Unix系统环境下的…

    2025年3月7日 编程技术
    200
  • Nodejs可以应用于那些场景?

    本篇文章给大家介绍一些nodejs的应用场景。有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助。 nodejsApache 的多线程高并发模式 优点:支持多线程并发 缺点:阻塞 nodejs什么是线程 线程是可以独立运行的最小…

    2025年3月7日
    200
  • 详解使用Docker给nodejs程序打包的方法

    本篇文章带大家了解一下docker,介绍为什么要使用 docker?如何使用 docker?以及使用docker给nodejs程序打包的方法。有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助。 你听到过这样的对话吗? 这种对话…

    2025年3月7日 编程技术
    200

发表回复

登录后才能评论