table drawing and options. no tags for table style. readme. see #117.

This commit is contained in:
Christopher Jeffrey 2015-04-02 17:59:04 -07:00
parent c8007331b0
commit f34cf1bdfe
5 changed files with 109 additions and 96 deletions

View File

@ -1128,7 +1128,9 @@ A stylized table of text elements.
- inherits all from Box.
- __rows/data__ - array of array of strings representing rows.
- __pad__ - spaces to attempt to pad on the sides of each cell. `2` by default:
one space on each side.
one space on each side (only useful if the width is shrunken).
- __noCellBorders__ - do not draw inner cells.
- __fillCellBorders__ - fill cell borders with the adjacent background color.
- __style.header__ - header style.
- __style.cell__ - cell style.
@ -1162,7 +1164,8 @@ A stylized table of text elements with a list.
- inherits all from List.
- __rows/data__ - array of array of strings representing rows.
- __pad__ - spaces to attempt to pad on the sides of each cell. `2` by default:
one space on each side.
one space on each side (only useful if the width is shrunken).
- __noCellBorders__ - do not draw inner cells.
- __style.header__ - header style.
- __style.cell__ - cell style.
@ -1318,15 +1321,15 @@ parent__, 50% as wide and 50% as tall as its parent.
To access the calculated offsets, relative to the parent:
``` js
console.log(box.rleft);
console.log(box.rtop);
console.log(box.left);
console.log(box.top);
```
To access the calculated offsets, absolute (relative to the screen):
``` js
console.log(box.left);
console.log(box.top);
console.log(box.aleft);
console.log(box.atop);
```
#### Overlapping offsets and dimensions greater than parents'
@ -1408,7 +1411,7 @@ event occurred on. Returning `false` will cancel propagation up the tree.
To actually render the screen buffer, you must call `render`.
``` js
box.setContent('Hello world.');
box.setContent('Hello {#0fe1ab-fg}world{/}.');
screen.render();
```
@ -1443,10 +1446,14 @@ This will actually parse the xterm terminfo and compile every
string capability to a javascript function:
``` js
var blessed = require('blessed')
, tput = blessed.tput('xterm-256color');
var blessed = require('blessed');
console.log(tput.setaf(4) + 'hello' + tput.sgr0());
var tput = blessed.tput({
terminal: 'xterm-256color',
extended: true
});
process.stdout.write(tput.setaf(4) + 'Hello' + tput.sgr0() + '\n');
```
To play around with it on the command line, it works just like tput:
@ -1454,7 +1461,7 @@ To play around with it on the command line, it works just like tput:
``` bash
$ tput.js setaf 2
$ tput.js sgr0
$ echo "$(tput.js setaf 2)hello world$(tput.js sgr0)"
$ echo "$(tput.js setaf 2)Hello World$(tput.js sgr0)"
```
The main functionality is exposed in the main `blessed` module:

View File

@ -2306,9 +2306,7 @@ Element.prototype.parseContent = function(noTags) {
};
Element.prototype.textLength = function(text) {
if (!this.options.tags && !this.options.parseTags) {
return text.length;
}
if (!this.parseTags) return text.length;
return text
.replace(/{(\/?)([\w\-,;!#]*)}/g, '')
.replace(/\x1b\[[\d;]*m/g, '')
@ -6967,8 +6965,6 @@ function Table(options) {
Box.call(this, options);
this.parseTags = true;
this.pad = options.pad != null
? options.pad
: 2;
@ -6989,18 +6985,21 @@ Table.prototype.type = 'table';
Table.prototype._calculateMaxes = function() {
var self = this;
var maxes = [];
var total = 1;
this.rows.forEach(function(row) {
row.forEach(function(cell, i) {
var clen = self.textLength(cell);
if (!maxes[i] || maxes[i] < clen + self.pad) {
maxes[i] = clen + self.pad;
total += maxes[i] + 1;
if (!maxes[i] || maxes[i] < clen) {
maxes[i] = clen;
}
});
});
var total = maxes.reduce(function(total, max) {
return total + max;
}, 0);
total += maxes.length + 1;
// XXX There might be an issue with resizing where on the first resize event
// width appears to be less than total if it's a percentage or left/right
// combination.
@ -7008,15 +7007,19 @@ Table.prototype._calculateMaxes = function() {
delete this.position.width;
}
if (this.position.width != null && this.width > total) {
var w = this.width / maxes.length | 0;
var wr = this.width % maxes.length;
var drawn = (maxes.length + 1) + (maxes.length * this.pad);
if (this.position.width != null) {
var missing = this.width - total;
var w = missing / maxes.length | 0;
var wr = missing % maxes.length;
maxes = maxes.map(function(max, i) {
if (i === maxes.length - 1) {
return max + w + wr - drawn;
return max + w + wr;
}
return max + w - drawn;
return max + w;
});
} else {
maxes = maxes.map(function(max) {
return max + self.pad;
});
}
@ -7030,9 +7033,6 @@ Table.prototype.setData = function(rows) {
, line = ''
, align = this.align;
var sheader = generateTags(this.style.header)
, scell = generateTags(this.style.cell);
this.rows = rows || [];
this._calculateMaxes();
@ -7074,16 +7074,6 @@ Table.prototype.setData = function(rows) {
}
}
if (!self.options.tags && !self.options.parseTags) {
cell = helpers.escape(cell);
}
if (isHeader) {
cell = sheader.open + cell + sheader.close;
} else {
cell = scell.open + cell + scell.close;
}
text += cell;
});
text += '\n';
@ -7120,12 +7110,17 @@ Table.prototype.render = function() {
, ry
, i;
var header = this.sattr(
var dattr = this.sattr(
this.style,
this.style.fg,
this.style.bg);
var hattr = this.sattr(
this.style.header,
this.style.header.fg,
this.style.header.bg);
var cell = this.sattr(
var cattr = this.sattr(
this.style.cell,
this.style.cell.fg,
this.style.cell.bg);
@ -7139,19 +7134,21 @@ Table.prototype.render = function() {
, height = coords.yl - coords.yi - this.iheight / 2;
// Apply attributes to header cells and cells.
// Problem: Does not allow for tags in cells.
// for (var y = this.iheight / 2; y < height; y++) {
// if (!lines[yi + y]) break;
// for (var x = this.iwidth / 2; x < width; x++) {
// if (y === this.iheight / 2) {
// lines[yi + y][xi + x][0] = header;
// } else {
// lines[yi + y][xi + x][0] = cell;
// }
// }
// }
for (var y = this.iheight / 2; y < height; y++) {
if (!lines[yi + y]) break;
for (var x = this.iwidth / 2; x < width; x++) {
if (!lines[yi + y][xi + x]) break;
// Check to see if it's not the default attr. Allows for tags:
if (lines[yi + y][xi + x][0] !== dattr) continue;
if (y === this.iheight / 2) {
lines[yi + y][xi + x][0] = hattr;
} else {
lines[yi + y][xi + x][0] = cattr;
}
}
}
if (!this.border) return coords;
if (!this.border || this.options.noCellBorders) return coords;
// Draw border with correct angles.
ry = 0;
@ -7161,6 +7158,7 @@ Table.prototype.render = function() {
self._maxes.forEach(function(max, i) {
rx += max;
if (i === 0) {
if (!lines[yi + ry][xi + 0]) return;
// left side
if (ry === 0) {
// top
@ -7176,6 +7174,7 @@ Table.prototype.render = function() {
lines[yi + ry][xi + 0][1] = '\u251c'; // '├'
}
} else if (i === self._maxes.length - 1) {
if (!lines[yi + ry][xi + rx + 1]) return;
// right side
if (ry === 0) {
// top
@ -7192,6 +7191,7 @@ Table.prototype.render = function() {
}
return;
}
if (!lines[yi + ry][xi + rx + 1]) return;
// center
if (ry === 0) {
// top
@ -7203,7 +7203,12 @@ Table.prototype.render = function() {
lines[yi + ry][xi + rx][1] = '\u2534'; // '┴'
} else {
// middle
lines[yi + ry][xi + ++rx][0] = battr;
if (self.options.fillCellBorders) {
var lbg = (ry <= 2 ? hattr : cattr) & 0x1ff;
lines[yi + ry][xi + ++rx][0] = (battr & ~0x1ff) | lbg;
} else {
lines[yi + ry][xi + ++rx][0] = battr;
}
lines[yi + ry][xi + rx][1] = '\u253c'; // '┼'
// ++rx;
}
@ -7217,8 +7222,14 @@ Table.prototype.render = function() {
rx = 0;
self._maxes.slice(0, -1).forEach(function(max, i) {
rx += max;
if (!lines[yi + ry][xi + rx + 1]) return;
if (ry % 2 !== 0) {
lines[yi + ry][xi + ++rx][0] = battr;
if (self.options.fillCellBorders) {
var lbg = (ry <= 2 ? hattr : cattr) & 0x1ff;
lines[yi + ry][xi + ++rx][0] = (battr & ~0x1ff) | lbg;
} else {
lines[yi + ry][xi + ++rx][0] = battr;
}
lines[yi + ry][xi + rx][1] = '\u2502'; // '│'
} else {
rx++;
@ -7228,7 +7239,14 @@ Table.prototype.render = function() {
self._maxes.forEach(function(max, i) {
while (max--) {
if (ry % 2 === 0) {
lines[yi + ry][xi + rx][0] = battr;
if (!lines[yi + ry]) break;
if (!lines[yi + ry][xi + rx + 1]) break;
if (self.options.fillCellBorders) {
var lbg = (ry <= 2 ? hattr : cattr) & 0x1ff;
lines[yi + ry][xi + rx][0] = (battr & ~0x1ff) | lbg;
} else {
lines[yi + ry][xi + rx][0] = battr;
}
lines[yi + ry][xi + rx][1] = '\u2500'; // '─'
}
rx++;
@ -7303,42 +7321,7 @@ ListTable.prototype.__proto__ = List.prototype;
ListTable.prototype.type = 'list-table';
ListTable.prototype._calculateMaxes = function() {
var self = this;
var maxes = [];
var total = 1;
this.rows.forEach(function(row) {
row.forEach(function(cell, i) {
var clen = self.textLength(cell);
if (!maxes[i] || maxes[i] < clen + self.pad) {
maxes[i] = clen + self.pad;
total += maxes[i] + 1;
}
});
});
// XXX There might be an issue with resizing where on the first resize event
// width appears to be less than total if it's a percentage or left/right
// combination.
if (this.width < total) {
delete this.position.width;
}
if (this.position.width != null && this.width > total) {
var w = this.width / maxes.length | 0;
var wr = this.width % maxes.length;
var drawn = (maxes.length + 1) + (maxes.length * this.pad);
maxes = maxes.map(function(max, i) {
if (i === maxes.length - 1) {
return max + w + wr - drawn;
}
return max + w - drawn;
});
}
return this._maxes = maxes;
};
ListTable.prototype._calculateMaxes = Table.prototype._calculateMaxes;
ListTable.prototype.setRows =
ListTable.prototype.setData = function(rows) {
@ -7443,7 +7426,7 @@ ListTable.prototype.render = function() {
var width = coords.xl - coords.xi - this.iwidth / 2
, height = coords.yl - coords.yi - this.iheight / 2;
if (!this.border) return coords;
if (!this.border || this.options.noCellBorders) return coords;
// Draw border with correct angles.
ry = 0;
@ -7452,6 +7435,7 @@ ListTable.prototype.render = function() {
rx = 0;
self._maxes.slice(0, -1).forEach(function(max, i) {
rx += max;
if (!lines[yi + ry][xi + rx + 1]) return;
// center
if (ry === 0) {
// top
@ -7475,7 +7459,13 @@ ListTable.prototype.render = function() {
rx = 0;
self._maxes.slice(0, -1).forEach(function(max, i) {
rx += max;
lines[yi + ry][xi + ++rx][0] = battr;
if (!lines[yi + ry][xi + rx + 1]) return;
if (self.options.fillCellBorders !== false) {
var lbg = lines[yi + ry][xi + rx][0] & 0x1ff;
lines[yi + ry][xi + ++rx][0] = (battr & ~0x1ff) | lbg;
} else {
lines[yi + ry][xi + ++rx][0] = battr;
}
lines[yi + ry][xi + rx][1] = '\u2502'; // '│'
});
}
@ -8340,7 +8330,7 @@ helpers.parseTags = function(text) {
helpers.generateTags = generateTags;
helpers.textLength = function(text) {
return Element.prototype.textLength.call({ options: { tags: true } }, text);
return Element.prototype.textLength.call({ parseTags: true }, text);
};
helpers.attrToBinary = function(obj, fg, bg, target) {

View File

@ -36,6 +36,14 @@ var table = blessed.listtable({
}
});
var data = [
[ 'Animals', 'Foods', 'Times', 'Numbers' ],
[ 'Elephant', 'Apple', '1:00am', 'One' ],
[ 'Bird', 'Orange', '2:15pm', 'Two' ],
[ 'T-Rex', 'Taco', '8:45am', 'Three' ],
[ 'Mouse', 'Cheese', '9:05am', 'Four' ]
];
var data = [
[ 'Animals', 'Foods', 'Times' ],
[ 'Elephant', 'Apple', '1:00am' ],

View File

@ -33,7 +33,7 @@ var logger = blessed.log({
logger.focus();
setInterval(function() {
logger.log('Hello {green-fg}world{/}: {bold}%s{/bold}.', Date.now().toString(36));
logger.log('Hello {#0fe1ab-fg}world{/}: {bold}%s{/bold}.', Date.now().toString(36));
if (Math.random() < 0.30) {
logger.log({foo:{bar:{baz:true}}});
}

View File

@ -29,6 +29,14 @@ var table = blessed.table({
}
});
var data = [
[ 'Animals', 'Foods', 'Times', 'Numbers' ],
[ 'Elephant', 'Apple', '1:00am', 'One' ],
[ 'Bird', 'Orange', '2:15pm', 'Two' ],
[ 'T-Rex', 'Taco', '8:45am', 'Three' ],
[ 'Mouse', 'Cheese', '9:05am', 'Four' ]
];
var data = [
[ 'Animals', 'Foods', 'Times' ],
[ 'Elephant', 'Apple', '1:00am' ],