javascript - Get ANSI color for character at index -
i have developed couleurs
npm package can set append rgb
method 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'
this works fine. what's proper way ansi color/style of character @ index i
?
probably can hacked regular expressions, i'm not sure if that's (however, if correct implementation available i'm not against it)... i'd prefer native way color/style accessing character interpreted tty.
> function getstyle (input, i) { /* style @ index `i` */ return style; } > getstyle("hello world!".rgb(255, 0, 0), 0); // style of first char { start: "\u001b[38;5;196m", end: "\u001b[0m", char: "h" } > getstyle("hello " + "world!".rgb(255, 0, 0), 0); // style of first char { start: "", end: "", char: "h" }
things complicated when have multiple combined styles:
> console.log("green , italic".rgb(0, 255, 0).italic()) green , italic undefined > getstyle("green , 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() + " 1 red").rgb(255, 0, 0), 0); { start: "\u001b[38;5;196m\u001b[1m", end: "\u001b[22m\u001b[0m", char: "b" } > getstyle(("bold & red".bold() + " 1 red").rgb(255, 0, 0), 11); { start: "\u001b[38;5;196m", end: "\u001b[0m", char: "u" } > ("bold & red".bold() + " 1 red").rgb(255, 0, 0) '\u001b[38;5;196m\u001b[1mbold & red\u001b[22m 1 red\u001b[0m'
like said, i'm looking native way (maybe using child process).
so, how complete ansi style character @ index i
?
there couple of ways 'add' formatting text, , 1 of them. problem mixing text , styling same object -- text string. it's similar rtf
here \b bold\b0 , {\i italic} text\par
but different from, say, native format of word .doc files, works text runs:
(text) here bold , italic text\r (chp) 13 none 4 sprmcfbold 5 none 6 sprmcfitalic 6 none
-- number @ left count of characters formatting.
the latter format looking for, since want index characters in plain text. subtracting formatting lengths show 1 interested in. depending on how many times expect ask formatting, can one-time runs only, or cache formatted text somewhere.
a one-time run needs inspect each element of encoded string, incrementing "text" index when not inside color string, , updating 'last seen' color string if is. added compatible getcharat
function debugging purposes.
var str = '\u001b[38;5;196m\u001b[1mbo\x1b[22mld & red\u001b[22m 1 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? (i=0; i<map.length; i++) { if (map[i][1] == cmatch[0]) { // remove on code? (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 { /* 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 { /* 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 '+color+color.length+', char '+text);
the returned color
still in original escaped encoding. can make return constant of kind adding these original map
array.
Comments
Post a Comment