docs. smartCSR option. minor fixes.

This commit is contained in:
Christopher Jeffrey 2013-07-15 01:44:11 -05:00
parent 158572ae38
commit 51413c346e
3 changed files with 180 additions and 91 deletions

View File

@ -152,6 +152,11 @@ The base node which everything inherits from.
- **prepend(node)** - prepend a node to this node's children.
- **append(node)** - append a node to this node's children.
- **remove(node)** - remove child node from node.
- **insert(node, i)** - insert a node to this node's children at index `i`.
- **insertBefore(node, refNode)** - insert a node to this node's children
before the reference node.
- **insertAfter(node, refNode)** - insert a node from node after the reference
node.
- **detach()** - remove node from its parent.
- **emitDescendants(type, args..., [iterator])** - emit event for element, and
recursively emit same event for all descendants.
@ -166,6 +171,10 @@ The screen on which every other node renders.
##### Options:
- **program** - the blessed Program to be associated with.
- **smartCSR** - attempt to perform CSR optimization on all possible elements
(not just full-width ones, elements with uniform cells to their sides).
this is known to cause flickering with elements that are not full-width,
however, it is more optimal for terminal rendering.
##### Properties:

View File

@ -310,6 +310,7 @@ function Screen(options) {
this.program.alternateBuffer();
this.program.hideCursor();
this.program.cup(0, 0);
this.alloc();
function reset() {
@ -591,7 +592,6 @@ Screen.prototype.insertLine = function(n, y, top, bottom) {
this.program.cup(y, 0);
this.program.il(n);
this.program.csr(0, this.height - 1);
this.program.cup(y, 0);
this.program.restoreCursor();
var j = this.rows - 1 - bottom;
@ -618,7 +618,6 @@ Screen.prototype.deleteLine = function(n, y, top, bottom) {
this.program.cup(y, 0);
this.program.dl(n);
this.program.csr(0, this.height - 1);
this.program.cup(y, 0);
this.program.restoreCursor();
var j = this.rows - 1 - bottom;
@ -673,6 +672,10 @@ Screen.prototype.cleanSides = function(el) {
return pos._cleanSides = true;
}
if (!this.options.smartCSR) {
return false;
}
var yi = pos.yi + (el.border ? 1 : 0) + el.padding
, yl = pos.yl - (el.border ? 1 : 0) - el.padding
, first
@ -881,6 +884,157 @@ Screen.prototype._reduceColor = function(col) {
return col;
};
// Convert an SGR string to our own attribute format.
Screen.prototype.attrCode = function(code, cur) {
var flags = (cur >> 18) & 0x1ff
, fg = (cur >> 9) & 0x1ff
, bg = cur & 0x1ff
, c
, i;
code = /^\x1b\[([\d;]*)m$/.exec(code);
if (!code) return cur;
code = code[1].split(';');
if (!code[0]) code[0] = '0';
for (i = 0; i < code.length; i++) {
c = +code[i] || 0;
switch (c) {
case 0: // normal
bg = 0x1ff;
fg = 0x1ff;
flags = 0;
break;
case 1: // bold
flags |= 1;
break;
case 22:
flags &= ~1;
break;
case 4: // underline
flags |= 2;
break;
case 24:
flags &= ~2;
break;
case 5: // blink
flags |= 4;
break;
case 25:
flags &= ~4;
break;
case 7: // inverse
flags |= 8;
break;
case 27:
flags &= ~8;
break;
case 8: // invisible
flags |= 16;
break;
case 28:
flags &= ~16;
break;
default: // color
if (c === 48 && code[i+1] === '5') {
i += 2;
bg = +code[i];
break;
} else if (c === 38 && code[i+1] === '5') {
i += 2;
fg = +code[i];
break;
}
if (c >= 40 && c <= 47) {
bg = c - 40;
} else if (c >= 100 && c <= 107) {
bg = c - 100;
bg += 8;
} else if (c === 49) {
bg = 0x1ff;
} else if (c >= 30 && c <= 37) {
fg = c - 30;
} else if (c >= 90 && c <= 97) {
fg = c - 90;
fg += 8;
} else if (c === 39) {
fg = 0x1ff;
}
break;
}
}
return (flags << 18) | (fg << 9) | bg;
};
// Convert our own attribute format to an SGR string.
Screen.prototype.codeAttr = function(code) {
var flags = (code >> 18) & 0x1ff
, fg = (code >> 9) & 0x1ff
, bg = code & 0x1ff
, out = '';
// bold
if (flags & 1) {
out += '1;';
}
// underline
if (flags & 2) {
out += '4;';
}
// blink
if (flags & 4) {
out += '5;';
}
// inverse
if (flags & 8) {
out += '7;';
}
// invisible
if (flags & 16) {
out += '8;';
}
if (bg !== 0x1ff) {
bg = this._reduceColor(bg);
if (bg < 16) {
if (bg < 8) {
bg += 40;
} else if (bg < 16) {
bg -= 8;
bg += 100;
}
out += bg + ';';
} else {
out += '48;5;' + bg + ';';
}
}
if (fg !== 0x1ff) {
fg = this._reduceColor(fg);
if (fg < 16) {
if (fg < 8) {
fg += 30;
} else if (fg < 16) {
fg -= 8;
fg += 90;
}
out += fg + ';';
} else {
out += '38;5;' + fg + ';';
}
}
if (out[out.length-1] === ';') out = out.slice(0, -1);
return '\x1b[' + out + 'm';
};
Screen.prototype.focus = function(offset) {
var shown = this.input.filter(function(el) {
return el.visible;
@ -1827,7 +1981,7 @@ Box.prototype.render = function(stop) {
for (; cci < ci; cci++) {
if (content[cci] === '\x1b') {
if (c = /^\x1b\[[\d;]*m/.exec(content.substring(cci))) {
attr = attrCode(c[0], attr);
attr = this.screen.attrCode(c[0], attr);
cci += c[0].length - 1;
}
}
@ -1854,7 +2008,7 @@ outer:
while (ch === '\x1b') {
if (c = /^\x1b\[[\d;]*m/.exec(content.substring(ci - 1))) {
ci += c[0].length - 1;
attr = attrCode(c[0], attr);
attr = this.screen.attrCode(c[0], attr);
ch = content[ci] || ' ';
ci++;
} else {
@ -2216,6 +2370,9 @@ ScrollableBox.prototype.scroll = function(offset) {
b = p.yl - (this.border ? 1 : 0) - this.padding - 1;
d = this.childBase - base;
// var attr = this.screen.olines[t][p.xi + (this.border ? 1 : 0) + this.padding][0];
// this.screen.program.write(this.screen.codeAttr(attr, this.screen));
if (d > 0 && d < visible) {
// scrolled down
this.screen.deleteLine(d, t, t, b);
@ -2224,6 +2381,8 @@ ScrollableBox.prototype.scroll = function(offset) {
d = -d;
this.screen.insertLine(d, t, t, b);
}
// this.screen.program.sgr0();
}
this.emit('scroll');
@ -3917,90 +4076,6 @@ Passbox.prototype.type = 'passbox';
* Helpers
*/
// Convert an SGR string to our own attribute format.
function attrCode(code, cur) {
var flags = (cur >> 18) & 0x1ff
, fg = (cur >> 9) & 0x1ff
, bg = cur & 0x1ff
, c
, i;
code = /^\x1b\[([\d;]*)m$/.exec(code);
if (!code) return cur;
code = code[1].split(';');
if (!code[0]) code[0] = '0';
for (i = 0; i < code.length; i++) {
c = +code[i] || 0;
switch (c) {
case 0: // normal
bg = 0x1ff;
fg = 0x1ff;
flags = 0;
break;
case 1: // bold
flags |= 1;
break;
case 22:
flags &= ~1;
break;
case 4: // underline
flags |= 2;
break;
case 24:
flags &= ~2;
break;
case 5: // blink
flags |= 4;
break;
case 25:
flags &= ~4;
break;
case 7: // inverse
flags |= 8;
break;
case 27:
flags &= ~8;
break;
case 8: // invisible
flags |= 16;
break;
case 28:
flags &= ~16;
break;
default: // color
if (c === 48 && code[i+1] === '5') {
i += 2;
bg = +code[i];
break;
} else if (c === 38 && code[i+1] === '5') {
i += 2;
fg = +code[i];
break;
}
if (c >= 40 && c <= 47) {
bg = c - 40;
} else if (c >= 100 && c <= 107) {
bg = c - 100;
bg += 8;
} else if (c === 49) {
bg = 0x1ff;
} else if (c >= 30 && c <= 37) {
fg = c - 30;
} else if (c >= 90 && c <= 97) {
fg = c - 90;
fg += 8;
} else if (c === 39) {
fg = 0x1ff;
}
break;
}
}
return (flags << 18) | (fg << 9) | bg;
}
function sp(line, width, align) {
if (!align) return line;

View File

@ -1,5 +1,10 @@
var blessed = require('blessed')
, screen = blessed.screen({ dump: __dirname + '/p.log' });
, screen;
screen = blessed.screen({
dump: __dirname + '/p.log',
smartCSR: true
});
var lorem = require('fs').readFileSync(__dirname + '/git.diff', 'utf8');
@ -16,6 +21,7 @@ function expectClean(value) {
};
}
/*
blessed.box({
parent: screen,
left: 0,
@ -26,8 +32,8 @@ blessed.box({
content: 'This will disallow CSR.'
});
expectClean(false);
*/
/*
blessed.box({
parent: screen,
left: 'center',
@ -41,7 +47,6 @@ blessed.box({
content: 'CSR should still work.'
});
expectClean(true);
*/
var text = blessed.scrollabletext({
parent: screen,