基于ANSI转义序列来构建命令行工具
栏目: JavaScript · 发布时间: 5年前
内容简介:命令行工具在输出时,如果是简单的进度更新,可以使用已有不少成熟的命令行工具库,如
命令行 工具 在输出时,如果是简单的进度更新,可以使用 \r
和 \b
来达成刷新行的效果,但如果要更复杂些的如字体颜色、背景颜色、光标位置移动等功能,那就需要使用 ANSI 转移序列了。
已有不少成熟的命令行工具库,如 Readline 、 JLine 和 Python Prompt Toolkit ,基于这些库创造了如 mycli 和 ipython 等好用的工具。
ANSI 转义序列 有比较悠久的历史,不同平台支持的功能不完全一致,这里学习到的是比较简单常用的,包括字体颜色、背景色和其它装饰的富文本和光标操作。
\u001b
即 ESC 的 ASCII 码, \u001b[0m
是清除之前的设定。
适用于 *nix 的系统。
富文本
前景色
8 色
\u001b[?m
,其中 ? ∈ [30, 37]
。
\u001b[30m \u001b[31m \u001b[32m \u001b[33m \u001b[34m \u001b[35m \u001b[36m \u001b[37m \u001b[0m
16 色
在 8 色的基础上对字体加粗,颜色加亮,得到另外 8 种,加起来就是 16 色。
\u001b[?;1m
,其中 ? ∈ [30, 37]
。
\u001b[30;1m \u001b[31;1m \u001b[32;1m \u001b[33;1m \u001b[34;1m \u001b[35;1m \u001b[36;1m \u001b[37;1m
const out = process.stdout; function colors8(pre, post, startCode = 30) { const codePointA = 'A'.codePointAt(0); let i = 0; while (i < 8) { const colorCode = startCode + i; const char = String.fromCodePoint(codePointA + i); out.write(`${pre}${colorCode}${post}${char} `); i++; } console.log('\u001b[0m'); } function fgColors8() { colors8('\u001b[', 'm'); } function fgColors8Bright() { colors8('\u001b[', ';1m'); } fgColors8(); fgColors8Bright();
256 色
\u001b[38;5;?m
,其中 ? ∈ [0, 255]
function colors256(pre, post) { let i = 0; while (i < 16) { let j = 0; while (j < 16) { const colorCode = i * 16 + j; const text = `${colorCode}`.padEnd(4); out.write(`${pre}${colorCode}${post}${text}`); j++; } console.log('\u001b[0m'); i++; } } function fgColors256() { colors256('\u001b[38;5;', 'm'); } fgColors256();
背景色
背景色和前景色的方案一致,只是 code 不同而已。
8 色
\u001b[?m
,其中 ? ∈ [40, 47]
。
\u001b[40m \u001b[41m \u001b[42m \u001b[43m \u001b[44m \u001b[45m \u001b[46m \u001b[47m
16 色
\u001b[?;1m
,其中 ? ∈ [40, 47]
。
\u001b[40;1m \u001b[41;1m \u001b[42;1m \u001b[43;1m \u001b[44;1m \u001b[45;1m \u001b[46;1m \u001b[47;1m
function bgColors8() { colors8('\u001b[', 'm', 40); } function bgColors8Bright() { colors8('\u001b[', ';1m', 40); } bgColors8(); bgColors8Bright();
256 色
\u001b[48;5;?m
,其中 ? ∈ [0, 255]
function bgColors256() { colors256('\u001b[48;5;', 'm'); } bgColors256();
装饰
\u001b[1m \u001b[2m \u001b[3m \u001b[4m \u001b[7m
可以单独使用,也可以组合使用(如 \u001b[1m\u001b[4m\u001b[7m
表示加粗、下划线和反色)。
还可以和颜色结合一起使用,如 \u001b[1m\u001b[4m\u001b[44m\u001b[31m Blue Background Red Color Bold Underline
。
function decorations() { const codes = [ [1, 'High'], [2, 'Low'], [3, 'Italic'], [4, 'Underline'], [7, 'Reverse'] ]; for (let c of codes) { out.write(`\u001b[${c[0]}m${c[1]} \u001b[0m`); } console.log(); console.log('\u001b[1m\u001b[4m\u001b[44m\u001b[31mBlue Background Red Color Bold Underline\u001b[0m'); } decorations();
光标操作
- 上:
\u001b[{n}A
,光标上移n
行 - 下:
\u001b[{n}B
,光标下移n
行 - 右:
\u001b[{n}C
,光标右移n
个位置 - 左:
\u001b[{n}D
,光标左移n
个位置 - 下几行行首:
\u001b[{n}E
- 上几行行首:
\u001b[{n}F
- 指定列:
\u001b[{n}G
- 指定位置:
\u001b[{n};{m}H
,移动光标到n
行m
列 - 清屏:
\u001b[{n}J
n=0 n=1 n=2
- 清行:
\u001b[{n}K
n=0 n=1 n=2
function sleep(ms) { return new Promise(resolve => { setTimeout(resolve, ms); }); } async function progressIndicator() { console.log('Loading...'); let i = 0; while(i <= 100) { await sleep(10); out.write(`\u001b[1000D${i}%`); i++; } // 清除进度信息(上两行)然后输出 Done! console.log('\u001b[2F\u001b[0JDone!'); } (async () => { await progressIndicator(); })();
async function progressBars(count = 1) { const list = []; let i = 0; while (i++ < count) { list[i] = 0; } // 占位提供空间 out.write(list.map(i => '').join('\n')); while(list.some(i => i< 100)) { await sleep(10); const unfinished = list.reduce((p, c, i) => { if (c < 100) p.push(i); return p; }, []); const randomIndex = unfinished[Math.floor(Math.random() * unfinished.length)]; list[randomIndex] += 1; out.write('\u001b[1000D'); out.write('\u001b[' + count + 'A'); list.forEach(p => { const width = Math.floor(p / 4); console.log('[' + '#'.repeat(width) + ' '.repeat(25-width) + ']'); }); } console.log(`\u001b[1000D\u001b[${count}A\u001b[0JDone!`); } (async () => { console.log('Single progress'); await progressBars(); console.log(); console.log('Multiple progress'); await progressBars(4); })();
参考
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 让控制台支持 ANSI 转义序列,输出下划线、修改颜色或其他控制
- PowerShell转义通配符
- XML 非法字符(转义字符)
- php 字符串转义
- Python处理HTML转义字符
- PHP 中的转义函数小结
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Language Implementation Patterns
Terence Parr / Pragmatic Bookshelf / 2010-1-10 / USD 34.95
Knowing how to create domain-specific languages (DSLs) can give you a huge productivity boost. Instead of writing code in a general-purpose programming language, you can first build a custom language ......一起来看看 《Language Implementation Patterns》 这本书的介绍吧!