Javascript 如何在不破坏ANSI转义码的情况下将字符串截断到最大长度
我在Node.js中有一个子进程,它生成的输出有时比我的终端宽Javascript 如何在不破坏ANSI转义码的情况下将字符串截断到最大长度,javascript,node.js,ansi-escape,Javascript,Node.js,Ansi Escape,我在Node.js中有一个子进程,它生成的输出有时比我的终端宽 我想截断长行,但不破坏ANSI颜色代码,也不计算不可见字符(这样带有大量转义符的行就不会太短)首先,您需要确保处理来自stdout的完整行,这可能会在行之间产生片段: var acc = ''; child.stdout.setEncoding('utf8'); // get strings rather than buffers child.stdout.on('data', function(data){ // wh
我想截断长行,但不破坏ANSI颜色代码,也不计算不可见字符(这样带有大量转义符的行就不会太短)首先,您需要确保处理来自
stdout
的完整行,这可能会在行之间产生片段:
var acc = '';
child.stdout.setEncoding('utf8'); // get strings rather than buffers
child.stdout.on('data', function(data){ // when output is written by child
// split lines, including linebreaks:
data.split(/(\r?\n)/).forEach(function(frag) {
if (frag == '\r\n' || frag == '\n') { // if linebreak,
console.log(filterAnsi(acc, width)); // output filtered completed line
acc = ''; // clear accumulator line
} else { // if not linebreak,
acc += frag; // add fragment to accumulator
}
});
});
接下来是过滤器本身:
// Crop the length of lines, ANSI escape code aware
// Always outputs every escape char, regardless of length (so we always end up with a sane state)
// Visible characters are filtered out once length is exceeded
function filterAnsi(str, len) {
if (!len || len < 10) return str; // probably not a valid console -- send back the whole line
var count = 0, // number of visible chars on line so far
esc = false, // in an escape sequence
longesc = false; // in a multi-character escape sequence
var outp = true; // should output this character
return str.split('').filter(function(c){ // filter characters...
if (esc && !longesc && c == '[') longesc = true; // have seen an escape, now '[', start multi-char escape
if (c == '\x1b') esc = true; // start of escape sequence
outp = (count < len || esc); // if length exceeded, don't output non-escape chars
if (!esc && !longesc) count++; // if not in escape, count visible char
if (esc && !longesc && c != '\x1b') esc = false; // out of single char escape
if (longesc && c != '[' && c >= '@' && c <= '~') {esc=false; longesc=false;} // end of multi-char escape
return outp; // result for filter
}).join(''); // glue chars back into string
}
//裁剪行的长度,ANSI转义码感知
//总是输出每个转义字符,不管长度如何(因此我们总是以一个正常状态结束)
//一旦超过长度,可见字符将被过滤掉
函数过滤器ASI(str,len){
如果(!len | | len<10)返回str;//可能不是一个有效的控制台——返回整行
var count=0,//到目前为止,行上的可见字符数
esc=false,//在转义序列中
longesc=false;//在多字符转义序列中
var outp=true;//应输出此字符
返回str.split(“”).filter(函数(c){//筛选字符。。。
如果(esc&&!longesc&&c='[')longesc=true;//已看到转义,现在为'[',启动多字符转义
如果(c=='\x1b')esc=true;//转义序列的开始
outp=(count 如果(longesc&&c!='['&&c>='@'&&c您可能想要尝试这个小小的NPM库:(注意:我是这个库的作者)
它通过处理包含零宽度字符和ANSI转义码的字符串来处理各种负担
在不破坏ANSI代码的情况下获取前N个符号:
const { first } = require ('printable-characters')
const s = '\u001b[22mfoobar\u001b[22m'
first (s, 0) // === '\u001b[22m\u001b[22m'
first (s, 1) // === '\u001b[22mf\u001b[22m'
first (s, 3) // === '\u001b[22mfoo\u001b[22m'
first (s, 6) // === '\u001b[22mfoobar\u001b[22m'