* Fix MCI colors. Everything working well so far!

This commit is contained in:
Bryan Ashby 2015-04-30 14:39:03 -06:00
parent 23a4344a4b
commit 04c85d2311
8 changed files with 142 additions and 95 deletions

View File

@ -21,7 +21,7 @@ function ANSIEscapeParser(options) {
this.column = 1; this.column = 1;
this.row = 1; this.row = 1;
this.scrollBack = 0; this.scrollBack = 0;
this.graphicRendition = { styles : [] }; this.graphicRendition = {};
options = miscUtil.valueWithDefault(options, { options = miscUtil.valueWithDefault(options, {
mciReplaceChar : '', mciReplaceChar : '',
@ -118,7 +118,7 @@ function ANSIEscapeParser(options) {
function getProcessedMCI(mci) { function getProcessedMCI(mci) {
if(self.mciReplaceChar.length > 0) { if(self.mciReplaceChar.length > 0) {
return ansi.getSGRFromGraphicRendition(self.graphicRendition) + new Array(mci.length + 1).join(self.mciReplaceChar); return ansi.getSGRFromGraphicRendition(self.graphicRendition, true) + new Array(mci.length + 1).join(self.mciReplaceChar);
} else { } else {
return mci; return mci;
} }
@ -161,10 +161,14 @@ function ANSIEscapeParser(options) {
} }
self.emit('mci', mciCode, id, args); self.emit('mci', {
mci : mciCode,
id : id ? parseInt(id, 10) : null,
args : args,
SGR : ansi.getSGRFromGraphicRendition(self.graphicRendition, true)
});
if(self.mciReplaceChar.length > 0) { if(self.mciReplaceChar.length > 0) {
//self.emit('chunk', ansi.sgr(self.eraseColor.style, self.eraseColor.fgColor, self.eraseColor.bgColor));
self.emit('chunk', ansi.getSGRFromGraphicRendition(self.graphicRenditionForErase)); self.emit('chunk', ansi.getSGRFromGraphicRendition(self.graphicRenditionForErase));
literal(new Array(match[0].length + 1).join(self.mciReplaceChar)); literal(new Array(match[0].length + 1).join(self.mciReplaceChar));
} else { } else {
@ -270,10 +274,6 @@ function ANSIEscapeParser(options) {
// set graphic rendition // set graphic rendition
case 'm' : case 'm' :
self.graphicRendition = { styles : [ 0 ] }; // reset
//self.graphicRendition.styles = [ 0 ];
for(i = 0, len = args.length; i < len; ++i) { for(i = 0, len = args.length; i < len; ++i) {
arg = args[i]; arg = args[i];
@ -281,18 +281,54 @@ function ANSIEscapeParser(options) {
self.graphicRendition.fg = arg; self.graphicRendition.fg = arg;
} else if(ANSIEscapeParser.backgroundColors[arg]) { } else if(ANSIEscapeParser.backgroundColors[arg]) {
self.graphicRendition.bg = arg; self.graphicRendition.bg = arg;
} else if(39 === arg) {
delete self.graphicRendition.fg;
} else if(49 === arg) {
delete self.graphicRendition.bg;
} else if(ANSIEscapeParser.styles[arg]) { } else if(ANSIEscapeParser.styles[arg]) {
self.graphicRendition.styles.push(arg); switch(arg) {
} else if(22 === arg) { case 0 :
// :TODO: remove bold. // clear out everything
delete self.graphicRendition.intensity;
delete self.graphicRendition.underline;
delete self.graphicRendition.blink;
delete self.graphicRendition.negative;
delete self.graphicRendition.invisible;
self.graphicRendition.fg = 39;
self.graphicRendition.bg = 49;
break;
case 1 :
case 2 :
case 22 :
self.graphicRendition.intensity = arg;
break;
case 4 :
case 24 :
self.graphicRendition.underline = arg;
break;
case 5 :
case 6 :
case 25 :
self.graphicRendition.blink = arg;
break;
case 7 :
case 27 :
self.graphicRendition.negative = arg;
break;
case 8 :
case 28 :
self.graphicRendition.invisible = arg;
break;
default :
console.log('Unknown attribute: ' + arg); // :TODO: Log properly
break;
}
} }
} }
console.log(self.graphicRendition)
break; break;
// erase display/screen // erase display/screen
@ -317,6 +353,8 @@ ANSIEscapeParser.foregroundColors = {
35 : 'magenta', 35 : 'magenta',
36 : 'cyan', 36 : 'cyan',
37 : 'white', 37 : 'white',
39 : 'default', // same as white for most implementations
90 : 'grey' 90 : 'grey'
}; };
Object.freeze(ANSIEscapeParser.foregroundColors); Object.freeze(ANSIEscapeParser.foregroundColors);
@ -329,20 +367,39 @@ ANSIEscapeParser.backgroundColors = {
44 : 'blue', 44 : 'blue',
45 : 'magenta', 45 : 'magenta',
46 : 'cyan', 46 : 'cyan',
47 : 'white' 47 : 'white',
49 : 'default', // same as black for most implementations
}; };
Object.freeze(ANSIEscapeParser.backgroundColors); Object.freeze(ANSIEscapeParser.backgroundColors);
// :TODO: ensure these all align with that of ansi_term.js // :TODO: ensure these names all align with that of ansi_term.js
//
// See the following specs:
// * http://www.ansi-bbs.org/ansi-bbs-core-server.html
// * http://www.vt100.net/docs/vt510-rm/SGR
// * https://github.com/protomouse/synchronet/blob/master/src/conio/cterm.txt
//
// Note that these are intentionally not in order such that they
// can be grouped by concept here in code.
//
ANSIEscapeParser.styles = { ANSIEscapeParser.styles = {
0 : 'default', 0 : 'default', // Everything disabled
1 : 'bright',
2 : 'dim', 1 : 'intensityBright', // aka bold
5 : 'slowBlink', 2 : 'intensityDim',
6 : 'fastBlink', 22 : 'intensityNormal',
7 : 'negative',
8 : 'concealed', 4 : 'underlineOn', // Not supported by most BBS-like terminals
22 : 'normal', 24 : 'underlineOff', // Not supported by most BBS-like terminals
27 : 'positive',
5 : 'blinkSlow', // blinkSlow & blinkFast are generally treated the same
6 : 'blinkFast', // blinkSlow & blinkFast are generally treated the same
25 : 'blinkOff',
7 : 'negativeImageOn', // Generally not supported or treated as "reverse FG & BG"
27 : 'negativeImageOff', // Generally not supported or treated as "reverse FG & BG"
8 : 'invisibleOn', // FG set to BG
28 : 'invisibleOff', // Not supported by most BBS-like terminals
}; };
Object.freeze(ANSIEscapeParser.styles); Object.freeze(ANSIEscapeParser.styles);

View File

@ -326,16 +326,35 @@ function sgr() {
// //
// Converts a Graphic Rendition object used elsewhere // Converts a Graphic Rendition object used elsewhere
// to a ANSI SGR sequence // to a ANSI SGR sequence.
// //
function getSGRFromGraphicRendition(graphicRendition) { function getSGRFromGraphicRendition(graphicRendition, initialReset) {
var sgrSeq = graphicRendition.styles.slice(0); // start out with styles var sgrSeq = [];
var styleCount = 0;
[ 'intensity', 'underline', 'blink', 'negative', 'invisible' ].forEach(function style(s) {
if(graphicRendition[s]) {
sgrSeq.push(graphicRendition[s]);
++styleCount;
}
});
if(!styleCount) {
sgrSeq.push(0);
}
if(graphicRendition.fg) { if(graphicRendition.fg) {
sgrSeq.push(graphicRendition.fg); sgrSeq.push(graphicRendition.fg);
} }
if(graphicRendition.bg) { if(graphicRendition.bg) {
sgrSeq.push(graphicRendition.bg); sgrSeq.push(graphicRendition.bg);
} }
if(initialReset) {
sgrSeq.unshift(0);
}
return sgr(sgrSeq); return sgr(sgrSeq);
} }

View File

@ -420,7 +420,7 @@ function display(options, cb) {
termWidth : options.client.term.termWidth, termWidth : options.client.term.termWidth,
}); });
var mci = {}; var mciMap = {};
var mciPosQueue = []; var mciPosQueue = [];
var parseComplete = false; var parseComplete = false;
@ -429,7 +429,7 @@ function display(options, cb) {
var onCPR = function(pos) { var onCPR = function(pos) {
if(mciPosQueue.length > 0) { if(mciPosQueue.length > 0) {
var forMapItem = mciPosQueue.shift(); var forMapItem = mciPosQueue.shift();
mci[forMapItem].position = pos; mciMap[forMapItem].position = pos;
if(parseComplete && 0 === mciPosQueue.length) { if(parseComplete && 0 === mciPosQueue.length) {
completed(); completed();
@ -445,50 +445,36 @@ function display(options, cb) {
// options.client.term.write(ansi.blinkNormal()); // options.client.term.write(ansi.blinkNormal());
} }
cb(null, mci); cb(null, mciMap);
} }
options.client.on('cursor position report', onCPR); options.client.on('cursor position report', onCPR);
parser.on('mci', function onMCI(mciCode, id, args) { parser.on('mci', function mciEncountered(mciInfo) {
// :TODO: ensure generatedId's do not conflict with any |id| // :TODO: ensure generatedId's do not conflict with any |id|
id = id || generatedId++; var id = _.isUndefined(mciInfo.id) ? generatedId++ : mciInfo.id;
var mapItem = mciCode + id; var mapKey = mciInfo.mci + id;
// :TODO: Avoid mutiple [] lookups here var mapEntry = mciMap[mapKey];
if(mci[mapItem]) { if(mapEntry) {
mci[mapItem].focusGraphicRendition = parser.graphicRendition; mapEntry.focusSGR = mciInfo.SGR;
mapEntry.focusArgs = mciInfo.args;
/*
mci[mapItem].focusColor = {
fg : parser.fgColor,
bg : parser.bgColor,
flags : parser.style,
};
*/
mci[mapItem].focusArgs = args;
} else { } else {
mci[mapItem] = { mciMap[mapKey] = {
args : args, args : mciInfo.args,
/* SGR : mciInfo.SGR,
color : { code : mciInfo.mci,
fg : parser.fgColor, id : id,
bg : parser.bgColor,
flags : parser.style,
},
*/
graphicRendition : parser.graphicRendition,
code : mciCode,
id : parseInt(id, 10),
}; };
mciPosQueue.push(mapItem); mciPosQueue.push(mapKey);
options.client.term.write(ansi.queryPos(), false); // :TODO: don't convert LF's options.client.term.write(ansi.queryPos(), false); // :TODO: don't convert LF's
} }
}); });
parser.on('chunk', function onChunk(chunk) { parser.on('chunk', function onChunk(chunk) {
options.client.term.write(chunk, false);// :TODO: don't convert LF's options.client.term.write(chunk, false);
}); });
parser.on('complete', function onComplete() { parser.on('complete', function onComplete() {

View File

@ -56,15 +56,11 @@ MCIViewFactory.prototype.createFromMCI = function(mci) {
var view; var view;
var options = { var options = {
client : this.client, client : this.client,
id : mci.id, id : mci.id,
color : mci.color, ansiSGR : mci.SGR,
focusColor : mci.focusColor, ansiFocusSGR : mci.focusSGR,
position : { x : mci.position[0], y : mci.position[1] },
graphicRendition : mci.graphicRendition,
focusGraphicRendition : mci.focusGraphicRendition,
position : { x : mci.position[0], y : mci.position[1] },
}; };
function setOption(pos, name) { function setOption(pos, name) {
@ -183,6 +179,7 @@ MCIViewFactory.prototype.createFromMCI = function(mci) {
break; break;
case 'TM' : case 'TM' :
// :TODO: convert to new Graphics Rendition system here:
if(mci.args.length > 0) { if(mci.args.length > 0) {
var color = { fg : parseInt(mci.args[0], 10), flags : 0 }; var color = { fg : parseInt(mci.args[0], 10), flags : 0 };
if(mci.args.length > 1) { if(mci.args.length > 1) {

View File

@ -112,19 +112,19 @@ function stylizeString(s, style) {
} }
// Based on http://www.webtoolkit.info/ // Based on http://www.webtoolkit.info/
function pad(s, len, padChar, dir, stringColor, padColor) { function pad(s, len, padChar, dir, stringSGR, padSGR) {
len = miscUtil.valueWithDefault(len, 0); len = miscUtil.valueWithDefault(len, 0);
padChar = miscUtil.valueWithDefault(padChar, ' '); padChar = miscUtil.valueWithDefault(padChar, ' ');
dir = miscUtil.valueWithDefault(dir, 'right'); dir = miscUtil.valueWithDefault(dir, 'right');
stringColor = miscUtil.valueWithDefault(stringColor, ''); stringSGR = miscUtil.valueWithDefault(stringSGR, '');
padColor = miscUtil.valueWithDefault(padColor, ''); padSGR = miscUtil.valueWithDefault(padSGR, '');
var padlen = len - s.length; var padlen = len - s.length;
switch(dir) { switch(dir) {
case 'L' : case 'L' :
case 'left' : case 'left' :
s = padColor + new Array(padlen).join(padChar) + stringColor + s; s = padSGR + new Array(padlen).join(padChar) + stringSGR + s;
break; break;
case 'C' : case 'C' :
@ -132,16 +132,16 @@ function pad(s, len, padChar, dir, stringColor, padColor) {
case 'both' : case 'both' :
var right = Math.ceil(padlen / 2); var right = Math.ceil(padlen / 2);
var left = padlen - right; var left = padlen - right;
s = padColor + new Array(left + 1).join(padChar) + stringColor + s + padColor + new Array(right + 1).join(padChar); s = padSGR + new Array(left + 1).join(padChar) + stringSGR + s + padSGR + new Array(right + 1).join(padChar);
break; break;
case 'R' : case 'R' :
case 'right' : case 'right' :
s = stringColor + s + padColor + new Array(padlen).join(padChar); s = stringSGR + s + padSGR + new Array(padlen).join(padChar);
break; break;
default : break; default : break;
} }
return stringColor + s; return stringSGR + s;
} }

View File

@ -81,11 +81,6 @@ TextView.prototype.setFocus = function(focused) {
this.redraw(); this.redraw();
console.log('---')
console.log(this.graphicRendition)
console.log(this.focusGraphicRendition)
console.log('---')
// position & SGR for cursor // position & SGR for cursor
this.client.term.write(ansi.goto(this.position.x, this.position.y + this.text.length)); this.client.term.write(ansi.goto(this.position.x, this.position.y + this.text.length));
this.client.term.write(this.getFocusSGR()); this.client.term.write(this.getFocusSGR());

View File

@ -64,8 +64,8 @@ function View(options) {
this.dimens.width = options.dimens.width; this.dimens.width = options.dimens.width;
} }
this.graphicRendition = options.graphicRendition || { fg : 7, bg : 0, styles : [ 0 ] }; this.ansiSGR = options.ansiSGR || ansi.getSGRFromGraphicRendition( { fg : 39, bg : 49 }, true);
this.focusGraphicRendition = options.focusGraphicRendition || this.graphicRendition; this.ansiFocusSGR = options.ansiFocusSGR || this.ansiSGR;
if(options.styleColor1) { if(options.styleColor1) {
this.styleColor1 = options.styleColor1; this.styleColor1 = options.styleColor1;
@ -167,20 +167,12 @@ View.prototype.setColor = function(color, bgColor, flags) {
}; };
*/ */
View.prototype.getGraphicRendition = function() {
return this.graphicRendition;
}
View.prototype.getFocusGraphicRendition = function() {
return this.focusGraphicRendition;
}
View.prototype.getSGR = function() { View.prototype.getSGR = function() {
return ansi.getSGRFromGraphicRendition(this.getGraphicRendition()); return this.ansiSGR;
} }
View.prototype.getFocusSGR = function() { View.prototype.getFocusSGR = function() {
return ansi.getSGRFromGraphicRendition(this.getFocusGraphicRendition()); return this.ansiFocusSGR;
} }
View.prototype.redraw = function() { View.prototype.redraw = function() {

View File

@ -184,6 +184,7 @@ function ViewController(options) {
setViewProp('maxLength'); setViewProp('maxLength');
setViewProp('width', function(v) { view.dimens.width = parseInt(v, 10); }); setViewProp('width', function(v) { view.dimens.width = parseInt(v, 10); });
// :TODO: This needs converted to new GraphicRendition object and possibly allow escaped ANSI SGR here if string
setViewProp('styleColor1', function(v) { setViewProp('styleColor1', function(v) {
if(!_.has(v, 'fg')) { if(!_.has(v, 'fg')) {
return; return;