Implement color code parsing, currently just strips all codes

This commit is contained in:
Mikko Ahlroth 2014-10-06 23:42:45 +03:00
parent b83b74ecf5
commit f0cbff637e
2 changed files with 185 additions and 49 deletions

View file

@ -15,6 +15,7 @@
.import "eventqueue.js" as EQ .import "eventqueue.js" as EQ
.import "moment.js" as M .import "moment.js" as M
.import "debug.js" as D .import "debug.js" as D
.import "weechatcolors.js" as WC
function Buffer(pointer, number, name, title) { function Buffer(pointer, number, name, title) {
this.pointer = pointer; this.pointer = pointer;
@ -157,7 +158,9 @@ function lineAdded(data) {
var buffer = data.buffer; var buffer = data.buffer;
var date = M.moment(data.date); var date = M.moment(data.date);
_buffers[buffer].add(date, data.prefix, data.message); var prefix = WC.codedText2StyledText(WC.parseString(data.prefix));
var message = WC.codedText2StyledText(WC.parseString(data.message));
_buffers[buffer].add(date, prefix, message);
} }
function _sortBuffersList() { function _sortBuffersList() {

View file

@ -11,12 +11,46 @@
// Protocol specific constants // Protocol specific constants
// Starting bytes // Starting bytes
var COLOR_START = 0x19; var COLOR_START = '\x19';
var SET_ATTR = 0x1A; var SET_ATTR = '\x1A';
var REMOVE_ATTR = 0x1B; var REMOVE_ATTR = '\x1B';
var RESET = 0x1C; var RESET = '\x1C';
var START_RE = /^(\u0019|\u001a|\u001b|\u001c)/; var START_RE = /(\x19|\x1A|\x1B|\x1C)/;
// Because Javascript does not have named captures, this regex is going to look
// a bit hairy. Here be dragons.
var STD_RE = '\\d{2}'; // STD color
var EXT_RE = '\\d{5}'; // EXT color
var EXT_CHAR = '@'; // Character which begins EXT color
var ATTR_CC = '[*!/_|]'; // Attribute character class for regex
var COLOR_RE_STR = '^(?:(?:' + EXT_CHAR + '(' + EXT_RE + '))'
+ '|(' + STD_RE + ')'
+ '|(?:F' + EXT_CHAR + '?(' + ATTR_CC + '*)(?:(' + EXT_RE + ')|(' + STD_RE + ')))'
+ '|(?:B(?:' + EXT_CHAR + '(' + EXT_RE + ')|(' + STD_RE + ')))'
+ '|(?:\\*' + EXT_CHAR + '?(' + ATTR_CC + '*)(?:(' + EXT_RE + ')|(' + STD_RE + '))(?:,(?:' + EXT_CHAR + '(' + EXT_RE + ')|(' + STD_RE + ')))?)'
+ '|(bF)|(bD)|(bB)|(b_)|(b-)|(b#)|(bi)|(bl)|(E)|(\\x1C))(.*)$';
var COLOR_RE = new RegExp(COLOR_RE_STR);
// Different indexes to the above regex
var STD_IDX = 2;
var EXT_IDX = 1;
var F_A_IDX = 3;
var F_STD_IDX = 5;
var F_EXT_IDX = 4;
var B_STD_IDX = 7;
var B_EXT_IDX = 6;
var AST_A_IDX = 8;
var AST_STD_IDX = 10;
var AST_EXT_IDX = 9;
var AST_BG_STD_IDX = 12;
var AST_BG_EXT_IDX = 11;
var E_IDX = 21;
var RST_IDX = 22;
// The rest are unused for now
var REST_IDX = 23;
// Attributes // Attributes
var ATTR_BOLD = '*'; var ATTR_BOLD = '*';
@ -25,55 +59,81 @@ var ATTR_ITALIC = '/';
var ATTR_UNDERLINE = '_'; var ATTR_UNDERLINE = '_';
var ATTR_KEEP = '|'; var ATTR_KEEP = '|';
// A WeeChat color
// is_ext is true if the color is extended,
// otherwise it is a standard color
function CodedTextColor(color, is_ext) {
this.color = color;
this.is_ext = is_ext;
}
// A section of text which has the given attributes: // A section of text which has the given attributes:
// fgColor: Foreground color as weechat color number // fgColor: Foreground color as CodedTextColor object
// bgColor: Background color --//-- // bgColor: Background color --//--
// attributes: List of attributes from the selection above, // attributes: List of attributes from the selection above,
// except ATTR_KEEP. // except ATTR_KEEP
function CodedTextSection(str, fgColor, bgColor, attributes) { // emphasize: Should this section be emphasized
function CodedTextSection(str, fgColor, bgColor, attributes, emphasize) {
this.str = str; this.str = str;
this.fgColor = fgColor; this.fgColor = fgColor;
this.bgColor = bgColor; this.bgColor = bgColor;
this.attributes = attributes; this.attributes = attributes;
this.emphasize = emphasize;
// Clone this object
this.clone = function () {
var ret = new CodedTextSection();
ret.str = this.str;
ret.fgColor = this.fgColor;
ret.bgColor = this.bgColor;
ret.attributes = this.attributes;
ret.emphasize = this.emphasize;
return ret;
};
} }
// Parse coded text and return list of CodedTextSection // Parse coded text and return list of CodedTextSection
function parseString(str) { function parseString(str) {
var out = []; var out = [];
var currentMode = null; var currentMode = null;
var currentFg = null; var currentSection = null;
var currentBg = null; var previousSection = null;
var currentAttr = [];
var currentStr = null; var currentStr = null;
var parts = str.split(START_RE); var parts = str.split(START_RE);
for (var i = 0; i < parts.length; ++i) { for (var i = 0; i < parts.length; ++i) {
// Every even index is a content part // Every even index is a content part
if ((i % 2) === 0) { if ((i % 2) === 0) {
// The first part won't have any extra info // The first is just a plain string so we will handle it in the else part
if (i !== 0) { if (i > 0) {
switch (currentMode) { switch (currentMode) {
case COLOR_START: case COLOR_START:
currentStr = parseColorStart(parts[i], currentFg, currentBg, currentAttr); currentSection = parseColorStart(parts[i], previousSection);
break; break;
case SET_ATTR: case SET_ATTR:
currentStr = parseSetAttr(parts[i], currentFg, currentBg, currentAttr); currentSection = parseSetAttr(parts[i], previousSection);
break; break;
case REMOVE_ATTR: case REMOVE_ATTR:
currentStr = parseRemoveAttr(parts[i], currentFg, currentBg, currentAttr); currentSection = parseRemoveAttr(parts[i], previousSection);
break; break;
case RESET: case RESET:
currentFg = null; currentSection = new CodedTextSection(parts[i]);
currentBg = null; currentSection.fgColor = null;
currentAttr = null; currentSection.bgColor = null;
currentSection.attributes = null;
break; break;
} }
} }
else {
currentSection = new CodedTextSection(parts[i]);
}
out.push(new CodedTextSection(currentStr, currentFg, currentBg, currentAttr)); out.push(currentSection);
previousSection = currentSection;
} }
// The odd parts give the next mode // The odd parts give the next mode
else { else {
@ -84,43 +144,116 @@ function parseString(str) {
return out; return out;
} }
function parseColorStart(part, currentFg, currentBg, currentAttr) { // Parse color code
var data = null; function parseColorStart(part, previousSection) {
var ret = previousSection.clone();
if (part[0] === 'F') { var match = COLOR_RE.exec(part);
data = parseASTD(part); if (!match) {
ret.str = part;
return ret;
} }
ret.str = match[REST_IDX];
if (match[STD_IDX]) {
ret.fgColor = new CodedTextColor(match[STD_IDX], false);
}
else if (match[EXT_IDX]) {
ret.fgColor = new CodedTextColor(match[EXT_IDX], true);
}
else if (match[F_A_IDX] !== undefined) {
ret.attributes = match[F_A_IDX];
if (match[F_STD_IDX]) {
ret.fgColor = new CodedTextColor(match[F_STD_IDX], false);
}
else if (match[F_EXT_IDX]) {
ret.fgColor = new CodedTextColor(match[F_EXT_IDX], true);
}
}
else if (match[B_STD_IDX]) {
ret.bgColor = new CodedTextColor(match[B_STD_IDX], false);
}
else if (match[B_EXT_IDX]) {
ret.bgColor = new CodedTextColor(match[B_EXT_IDX], true);
}
else if (match[AST_A_IDX] !== undefined) {
ret.attributes = match[AST_A_IDX];
if (match[AST_STD_IDX]) {
ret.fgColor = new CodedTextColor(match[AST_STD_IDX], false);
}
else if (match[AST_EXT_IDX]) {
ret.fgColor = new CodedTextColor(match[AST_EXT_IDX], true);
}
if (match[AST_BG_STD_IDX]) {
ret.bgColor = new CodedTextColor(match[AST_BG_STD_IDX], false);
}
else if (match[AST_BG_EXT_IDX]) {
ret.bgColor = new CodedTextColor(match[AST_BG_EXT_IDX], true);
}
}
else if (match[E_IDX]) {
ret.emphasize = true;
}
else if (match[RST_IDX]) {
ret.fgColor = null;
ret.bgColor = null;
ret.attributes = null;
ret.emphasize = null;
}
return ret;
} }
function parseSetAttr(part, currentFg, currentBg, currentAttr) { // Parse attribute setting
function parseSetAttr(part, previousSection) {
var attr = part[0];
var ret = previousSection.clone();
ret.str = part.substr(1);
if (ret.attributes === null) {
ret.attributes = [attr];
}
else {
ret.attributes.push(attr);
}
return ret;
} }
function parseRemoveAttr(part, currentFg, currentBg, currentAttr) { // Parse attribute removal
function parseRemoveAttr(part, previousSection) {
var attr = part[0];
var ret = previousSection.clone();
ret.str = part.substr(1);
if (ret.attributes === null) {
return ret;
}
else {
var i = ret.attributes.find(attr);
if (i >= 0) {
ret.attributes.splice(i, 1);
}
}
return ret;
} }
// Parse STD (standard color), removing it from the beginning of string // Convert a list of sections into Qt styled text and
function parseSTD(str) { // return as a string
// TODO: Currently strips all styling
} function codedText2StyledText(sectionList) {
var ret = '';
// Parse EXT (extended color), --//--
function parseEXT(str) {
}
// Parse attributes + STD
function parseASTD(str) {
}
// Parse attributes + EXT
function parseAEXT(str) {
}
// Parse single attribute
function parseATTR(str) {
for (var i = 0; i < sectionList.length; ++i) {
var section = sectionList[i];
ret += section.str;
}
return ret;
} }