获取索引处字符的ANSI颜色 [英] Get ANSI color for character at index

查看:89
本文介绍了获取索引处字符的ANSI颜色的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我开发了 couleurs NPM包可以设置为 rgb 方法附加到 String.prototype

I have developed couleurs NPM package which can be set to append rgb method to String.prototype:

> console.log("Hello World!".rgb(255, 0, 0)) // "Hello World!" in red
Hello World!
undefined
> "Hello World!".rgb(255, 0, 0)
'\u001b[38;5;196mHello World!\u001b[0m'

这很好用。在索引 i 获得ANSI颜色/字符样式的正确方法是什么?

This works fine. What's the proper way to get the ANSI color/style of character at index i?

可能这可能被黑客入侵有一些正则表达式,但我不确定这是否真的很好(但是,如果一个正确的实现可用,我不反对它)...我更喜欢通过本机方式获取颜色/样式由tty解释的字符。

Probably this can be hacked with some regular expressions, but I'm not sure if that's really good (however, if a correct implementation is available I'm not against it)... I'd prefer a native way to get the color/style by accessing the character interpreted by tty.

> function getStyle (input, i) { /* get style at index `i` */ return style; }

> getStyle("Hello World!".rgb(255, 0, 0), 0); // Get style of the first char
{
   start: "\u001b[38;5;196m",
   end: "\u001b[0m",
   char: "H"
}
> getStyle("Hello " + "World!".rgb(255, 0, 0), 0); // Get style of the first char
{
   start: "",
   end: "",
   char: "H"
}

当我们有多种组合风格时,事情变得复杂:

Things get complicated when we have multiple combined styles:

> console.log("Green and Italic".rgb(0, 255, 0).italic())
Green and Italic
undefined
> getStyle("Green and Italic".rgb(0, 255, 0).italic(), 0);
{
   start: "\u001b[3m\u001b[38;5;46m",
   end: "\u001b[0m\u001b[23m",
   char: "G"
}
> getStyle(("Bold & Red".bold() + " but this one is only red").rgb(255, 0, 0), 0);
{
   start: "\u001b[38;5;196m\u001b[1m",
   end: "\u001b[22m\u001b[0m",
   char: "B"
}
> getStyle(("Bold & Red".bold() + " but this one is only red").rgb(255, 0, 0), 11);
{
   start: "\u001b[38;5;196m",
   end: "\u001b[0m",
   char: "u"
}
> ("Bold & Red".bold() + " but this one is only red").rgb(255, 0, 0)
'\u001b[38;5;196m\u001b[1mBold & Red\u001b[22m but this one is only red\u001b[0m'

就像我说的,我正在寻找一种本地方式(可能使用子进程)。

Like I said, I'm looking for a native way (maybe using a child process).

那么,如何在索引我?

推荐答案

有几种方法可以向文本添加格式,以及这是其中之一。问题是你将文本和样式混合到同一个对象 - 文本字符串。它类似于RTF

There are a couple of ways to 'add' formatting to text, and this is one of them. The problem is you are mixing text and styling into the same object -- a text string. It's similar to RTF

Here is some \b bold\b0 and {\i italic} text\par

但不同于Word .DOC文件的原生格式,适用于文本运行

but different from, say, the native format of Word .DOC files, which works with text runs:

(text) Here is some bold and italic text\r
(chp)  13 None
       4  sprmCFBold
       5  None
       6  sprmCFItalic
       6  None

- 左边的数字是具有特定格式的字符数。

-- the number at the left is the count of characters with a certain formatting.

后一种格式是您要查找的格式,因为您要在纯文本中索引字符。减去格式化长度将显示您感兴趣的格式。根据您要求格式化的次数,您可以只执行一次性运行,或者将格式化文本缓存到某处。

The latter format is what you are looking for, since you want to index characters in the plain text. Subtracting the formatting lengths will show which one you are interested in. Depending on how many times you expect to ask for a formatting, you can do one-time runs only, or cache the formatted text somewhere.

一次性运行需要检查编码字符串的每个元素,在不在颜色字符串内时递增text索引,并更新last seen颜色字符串(如果是)。我添加了一个兼容的 getCharAt 函数用于调试目的。

A one-time run needs to inspect each element of the encoded string, incrementing the "text" index when not inside a color string, and updating the 'last seen' color string if it is. I added a compatible getCharAt function for debugging purposes.

var str = '\u001b[38;5;196m\u001b[1mBo\x1B[22mld & Red\u001b[22m but this one is only red\u001b[0m';

const map = {
    bold: ["\x1B[1m", "\x1B[22m" ]
  , italic: ["\x1B[3m", "\x1B[23m" ]
  , underline: ["\x1B[4m", "\x1B[24m" ]
  , inverse: ["\x1B[7m", "\x1B[27m" ]
  , strikethrough: ["\x1B[9m", "\x1B[29m" ]
};

String.prototype.getColorAt = function(index)
{
    var strindex=0, color=[], cmatch, i,j;

    while (strindex < this.length)
    {
        cmatch = this.substr(strindex).match(/^(\u001B\[[^m]*m)/);
        if (cmatch)
        {
            // Global reset?
            if (cmatch[0] == '\x1B[0m')
            {
                color = [];
            } else
            {
                // Off code?
                for (i=0; i<map.length; i++)
                {
                    if (map[i][1] == cmatch[0])
                    {
                        // Remove On code?
                        for (j=color.length-1; j>=0; j--)
                        {
                            if (color[j] == map[i][0])
                                color.splice (j,1);
                        }
                        break;
                    }
                }
                if (j==map.length)
                    color.push (cmatch[0]);
            }
            strindex += cmatch[0].length;
        } else
        {
            /* a regular character! */
            if (!index)
                break;
            strindex++;
            index--;
        }
    }
    return color.join('');
}

String.prototype.getCharAt = function(index)
{
    var strindex=0, cmatch;

    while (strindex < this.length)
    {
        cmatch = this.substr(strindex).match(/^(\u001B\[[^m]*m)/);
        if (cmatch)
        {
            strindex += cmatch[0].length;
        } else
        {
            /* a regular character! */
            if (!index)
                return this.substr(strindex,1);
            strindex++;
            index--;
        }
    }
    return '';
}

console.log (str);

color = str.getColorAt (1);
text = str.getCharAt (1);
console.log ('color is '+color+color.length+', char is '+text);

返回的颜色仍然是原来的转义编码。您可以通过将这些常量添加到原始 map 数组中来使其返回某种常量。

The returned color is still in its original escaped encoding. You can make it return a constant of some kind by adding these into your original map array.

这篇关于获取索引处字符的ANSI颜色的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆