【问题标题】:How can I truncate a string to a maximum length without breaking ANSI escape codes如何在不破坏 ANSI 转义码的情况下将字符串截断为最大长度
【发布时间】:2014-10-07 14:35:18
【问题描述】:

我在 Node.js 中有一个子进程,它产生 ANSI-escape 彩色输出,有时比我的终端宽。

我想截断长行,但不破坏 ANSI 颜色代码,也不计算不可见字符(这样有很多转义的行不会短)

【问题讨论】:

    标签: javascript node.js ansi-escape


    【解决方案1】:

    首先,您需要确保处理来自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
    }
    

    【讨论】:

      【解决方案2】:

      你可能想试试这个小型 NPM 库:printable-characters(注意:我是这个库的作者

      它通过处理包含零宽度字符和 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'
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-07-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-11-19
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多