mirror of
https://github.com/embarklabs/neo-blessed.git
synced 2025-02-02 22:24:55 +00:00
table drawing and options. no tags for table style. readme. see #117.
This commit is contained in:
parent
c8007331b0
commit
f34cf1bdfe
29
README.md
29
README.md
@ -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:
|
||||
|
158
lib/widget.js
158
lib/widget.js
@ -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) {
|
||||
|
@ -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' ],
|
||||
|
@ -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}}});
|
||||
}
|
||||
|
@ -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' ],
|
||||
|
Loading…
x
Reference in New Issue
Block a user