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 "moment.js" as M
.import "debug.js" as D
.import "weechatcolors.js" as WC
function Buffer(pointer, number, name, title) {
this.pointer = pointer;
@ -157,7 +158,9 @@ function lineAdded(data) {
var buffer = data.buffer;
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() {

View file

@ -11,12 +11,46 @@
// Protocol specific constants
// Starting bytes
var COLOR_START = 0x19;
var SET_ATTR = 0x1A;
var REMOVE_ATTR = 0x1B;
var RESET = 0x1C;
var COLOR_START = '\x19';
var SET_ATTR = '\x1A';
var REMOVE_ATTR = '\x1B';
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
var ATTR_BOLD = '*';
@ -25,55 +59,81 @@ var ATTR_ITALIC = '/';
var ATTR_UNDERLINE = '_';
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:
// fgColor: Foreground color as weechat color number
// fgColor: Foreground color as CodedTextColor object
// bgColor: Background color --//--
// attributes: List of attributes from the selection above,
// except ATTR_KEEP.
function CodedTextSection(str, fgColor, bgColor, attributes) {
// except ATTR_KEEP
// emphasize: Should this section be emphasized
function CodedTextSection(str, fgColor, bgColor, attributes, emphasize) {
this.str = str;
this.fgColor = fgColor;
this.bgColor = bgColor;
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
function parseString(str) {
var out = [];
var currentMode = null;
var currentFg = null;
var currentBg = null;
var currentAttr = [];
var currentSection = null;
var previousSection = null;
var currentStr = null;
var parts = str.split(START_RE);
for (var i = 0; i < parts.length; ++i) {
// Every even index is a content part
if ((i % 2) === 0) {
// The first part won't have any extra info
if (i !== 0) {
// The first is just a plain string so we will handle it in the else part
if (i > 0) {
switch (currentMode) {
case COLOR_START:
currentStr = parseColorStart(parts[i], currentFg, currentBg, currentAttr);
currentSection = parseColorStart(parts[i], previousSection);
break;
case SET_ATTR:
currentStr = parseSetAttr(parts[i], currentFg, currentBg, currentAttr);
currentSection = parseSetAttr(parts[i], previousSection);
break;
case REMOVE_ATTR:
currentStr = parseRemoveAttr(parts[i], currentFg, currentBg, currentAttr);
currentSection = parseRemoveAttr(parts[i], previousSection);
break;
case RESET:
currentFg = null;
currentBg = null;
currentAttr = null;
currentSection = new CodedTextSection(parts[i]);
currentSection.fgColor = null;
currentSection.bgColor = null;
currentSection.attributes = null;
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
else {
@ -84,43 +144,116 @@ function parseString(str) {
return out;
}
function parseColorStart(part, currentFg, currentBg, currentAttr) {
var data = null;
// Parse color code
function parseColorStart(part, previousSection) {
var ret = previousSection.clone();
if (part[0] === 'F') {
data = parseASTD(part);
var match = COLOR_RE.exec(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;
}
// 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;
}
// 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);
}
}
function parseSetAttr(part, currentFg, currentBg, currentAttr) {
return ret;
}
function parseRemoveAttr(part, currentFg, currentBg, currentAttr) {
// Convert a list of sections into Qt styled text and
// return as a string
// TODO: Currently strips all styling
function codedText2StyledText(sectionList) {
var ret = '';
for (var i = 0; i < sectionList.length; ++i) {
var section = sectionList[i];
ret += section.str;
}
// Parse STD (standard color), removing it from the beginning of string
function parseSTD(str) {
}
// 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) {
return ret;
}