获取索引处字符的ANSI颜色 [英] Get ANSI color for character at index
问题描述
我开发了 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屋!