终端中的彩色文本控制指令的格式构成简介

ANSI Escape Code是一种带内信令(In-band signaling)的转义序列标准,用于控制文本在终端上的光标位置、颜色和其他选项。在文本中嵌入确定的字节序列,大部分以 ESC 转义字符和 “[” 字符开始,终端会把这些字节序列解释为相应的指令,而不是普通的字符编码。

ANSI 转义序列中以 ESC [(即\x1b[) 开头的叫作 Control Sequence Introducer,简写为 CSI。终端会将 CSI 字节序列解释为具有相应含义的指令。以 CSI 开头的指令有很多,大致可分四类:光标移动指令、清屏指令、字符渲染(Graphic Rendition)指令和终端控制指令。

基于 CSI 控制指令可以实现的功能是非常丰富的。如果你使用过支持 telnet 的 BBS 论坛的话,应该会有所了解。例如,你可以在终端中执行如下命令,以 telnet 的方式访问水木社区体验一下其魅力:

telnet bbs.newsmth.net

1 ANSI colors 颜色设置控制符号

CSI 指令中有颜色相关的控制指令字符。按照表示颜色的形式和范围的不同,可将它们分为三类:

  • 3/4 位颜色表示法
  • 8 位颜色表示法
  • 24 位颜色表示法, 支持 RGB 色值

ANSI 转义字符序列的控制字符范围及含义,可以查阅维基百科了解详情: ANSI转义序列

npmjs 上有许多基于ANSI color styles指令封装的控制台颜色格式化工具包,如:

在这些工具库中,只有 chalk 实现了全部ANSI colors 颜色设置的接口封装支持,并将其作为独立 npm 包 ansi-styles 进行维护(chalk 5项目则将 ansi-styles 的主 js 文件进行了内置)。

2 3/4位颜色表示法

基本格式为: \x1b[< N>m[字符]\x1b[< M>m

其中 NM 分别表示控制字符和结束字符,可查表了解其含义。如:

  • 前景色(彩色文本):\x1b[< N>m[字符]\x1b[39m。其中 N 取值范围 30<=n<=37
  • 背景色(彩色背景):\x1b[< N>m[字符]\x1b[49m。其中 N 取值范围 40<=n<=47

示例:

console.log('\x1b[92m\x1b[4mUnderline that text\x1b[0m');

var greenStr = '\x1b[32m This is a green string! \x1b[39m';
console.log(greenStr);

3 8位颜色表示法

基本格式为: \x1b[< 38|48>;5;< N>m[字符]\x1b[0m

其中38表示选择前景色,48表示选择背景色,N 取值范围0~255,可表示 256 种颜色。末尾的\x1b[0m表示重置设置。

示例:

console.log('\x1b[38;5;214mFirst some yellow text\x1b[0m', 'reseted');

ANSI colors 8位表示法全部前景色示例:

function printColors256() {
    const colorList = [''];
    const bgcolorList = [''];
    let idx = 0;

    while(idx++ < 256) {
        colorList.push(`\x1b[38;5;${idx}m${String(idx).padEnd(3, ' ')}\x1b[0m ${idx % 16 ? '' : '\n'}`);
        bgcolorList.push(`\x1b[48;5;${idx}m${String(idx).padEnd(3, ' ')}\x1b[0m ${idx % 16 ? '' : '\n'}`);
    }
    console.log(`ANSI 256 colors:\n${ colorList.join('') }`);
    console.log(`ANSI 256 background colors:\n${bgcolorList.join('')}`);
}
printColors256();

ANSI colors 256 示例:

function rainbow(words, startPos = Math.ceil(Math.random() * 100)) {
  // const colorCodes = new Array(256).fill().map(() => Math.floor(Math.random() * 255));
  const colorCodes = [196, 214, 32, 42, 46, 53, 79, 126, 205, 196, 39, 227];
  const str = words
    .split(' ')
    .map(word =>
      word
        .split('')
        .map((ch, idx) => `\x1b[38;5;${colorCodes[(idx + startPos) % colorCodes.length]}m${ch}\x1b[0m`)
        .join('')
    )
    .join(' ');
  console.log(str);
}

rainbow('Her wishful face haunts my dreams like the rain at night.');

4 24位颜色表示法

基本格式为: \x1b[< 38|48>;2;< R>;< G>;< B>m

  • 其中38表示选择前景色,48表示选择背景色
  • RGB 表示三原色,取值范围分别都是 0~255

示例:

console.log('\x1b[38;2;25;154;48m透过你的眼 \x1b[38;2;255;154;48m离别也是诗 \x1b[0m');
console.log('\x1b[48;2;48;154;255m \x1b[38;2;255;255;255m 偶尔还是需要出去走一走,才知道躺在床上多么舒服 \x1b[0m');

RGB 模式可以有 1600+ 万种颜色组合,可以支持的色彩相当丰富了。但并不是所有的终端都支持该模式。

值得一提的是,从 Chrome 69 开始,其浏览器控制台增加了 ANSI Escape colors 的编码指令支持。经过测试,其控制台支持 3/4位表示法和24位表示法的完整格式。你可以复制上面的相关例子,在 Chrome Console 控制台测试体验。

5 小结

关于 ANSI Escape Code 相关基础知识的细节,如有兴趣可参阅以下链接中的文档或文章进一步了解:

本文正在参加「金石计划 . 瓜分6万现金大奖」

© 版权声明
THE END
喜欢就支持一下吧
点赞5 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容