Implement color code parsing, currently just strips all codes
This commit is contained in:
parent
b83b74ecf5
commit
f0cbff637e
2 changed files with 185 additions and 49 deletions
|
@ -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() {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue