Files
nexe/node_modules/celeri/lib/modules/table.js
T
2011-11-26 17:00:12 -06:00

292 lines
6.2 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
var Structr = require('structr');
exports.plugin = function(cli)
{
function normalizeOptions(ops)
{
var cliWidth = cli.columns();
var columns = ops.columns,
normCols = [],
vert = ops.vertical || ops.vert || ' ',
horz = ops.horizontal || ops.horz || '',
pad = Structr.copy(ops.pad, { left: 0, right: 0, top: 0, bottom: 0 });
if(ops.padRight) pad.right = ops.padRight;
if(ops.padLeft) pad.left = ops.padLeft;
if(ops.padTop) pad.top = ops.padTop;
if(ops.padBottom) pad.bottom = ops.padBottom;
if(!ops.width) ops.width = cliWidth;
ops.width = Math.min(ops.width, cliWidth - pad.left - pad.right);
if(ops.border)
{
if(vert == ' ') vert = ' | ';
if(horz == '') horz = '';
}
//sum width of all columns combined
var sumWidth = 0;
for(var prop in columns)
{
var columnValue = columns[prop],
normCol = { minWidth: 6, align: 'left' },
tocv = typeof columnValue;
normCols.push(normCol)
//['columnName']
if(tocv == 'string')
{
normCol.name = columnValue;
}
else
{
//{columnName:value}
if(typeof prop == 'string')
{
normCol.name = prop;
}
if(tocv == 'number')
{
normCol.width = columnValue;
}
else
if(tocv == 'object')
{
Structr.copy(columnValue, normCol);
}
}
if(!normCol.width) normCol.width = 100/columns.length;
sumWidth += normCol.width;
}
//subtract vert padding
var sumActualWidth = 0,
colsTaken = 0,
numCols = normCols.length;
var tableWidth = ops.width - vert.length * numCols;
for(var i = 0; i < numCols; i++)
{
var column = normCols[i]/*,
isLast = i == numCols-1,
align = column.align;
if(!align)
{
column.align = isLast ? 'right' : 'left';
}*/
var percWidth = Math.round(column.width/sumWidth * tableWidth);
actualWidth = Math.max(column.minWidth, percWidth),
//diff between calculated perc width, and min width. used for penalization
difference = actualWidth - percWidth;
sumActualWidth += actualWidth;
//this may happen if there are too many minWidths specified. In which case, not all columns
//will be shown. Actual width will be set to zero
if(sumActualWidth > ops.width) actualWidth -= Math.min(actualWidth, sumActualWidth - tableWidth);
//actual width CANNOT be less than min width. e.g: single char column couold be huge.
if(actualWidth < column.minWidth) actualWidth = 0;
column.actualWidth = actualWidth;
//penalize the rest of the columns. Width must *not* cli width
sumWidth -= difference;
}
return {
columns: normCols,
ellipsis: ops.ellipsis,
vert: vert,
horz: horz,
pad: pad,
width: ops.width,
numColumns: numCols,
showLabels: !!ops.showLabels
}
}
function addLines(colLines, value, column)
{
var newLines = (value ? value.toString() : '').split(/[\r\n]/g);
for(var i = 0, n = newLines.length; i < n; i++)
{
//trim whitespace off the ends. line breaks = whitespace
var buffer = newLines[i].replace(/^\s+|\s+$/g,'');
var colors = buffer.match(/\u001b\[\d+m/g) || [];
var padding = column.actualWidth - buffer.length + colors.join('').length;
switch(column.align)
{
case 'right':
buffer = cli.utils.padLeft(buffer, padding, ' ');
break;
case 'center':
buffer = cli.utils.pad(buffer, Math.floor(padding/2), ' ', Math.ceil(padding/2));
break;
default:
buffer = cli.utils.padRight(buffer, padding, ' ');
break;
}
colLines.push(buffer);
}
}
function getRowLineTable(item, ops)
{
var lineTable = [],
numLines = 0,
cols = ops.numColumns;
//get the lines.
for(var j = 0, jn = cols; j < jn; j++)
{
var column = ops.columns[j],
value = item[ops.columns[j].name] || '',
colLines = [],
actualWidth = column.actualWidth;
//width not present? skip the column
if(!actualWidth) continue;
if(value.length > actualWidth)
{
if(ops.ellipsis)
{
var newBuffer = value.substr(0, actualWidth-3) + cli.utils.repeat('.', Math.min(actualWidth, 3));
addLines(colLines, newBuffer, column);
}
else
{
var start = 0;
//splice apart the single line, treating each chunk as a new line
for(var k = actualWidth; k < value.length + actualWidth; k += actualWidth)
{
addLines(colLines, value.substr(start, actualWidth), column);
start = k;
}
}
}
else
{
addLines(colLines, value, column);
}
//if this column lines
numLines = Math.max(numLines, colLines.length);
//next add the line - need to check against all lines now
lineTable.push(colLines);
//need to go through all the column lines again, and
//make sure all the lines match up properly
for(var k = 0, kn = lineTable.length; k < kn; k++)
{
var line = lineTable[k];
//must have same number of lineTable
if(line.length < numLines)
{
addLines(lineTable[k], cli.utils.repeat('\n', numLines - line.length -1), ops.columns[k]);
}
}
}
var rows = [];
//inversed
for(var i = 0, n = lineTable.length; i < n; i++)
{
var col = lineTable[i];
//each row
for(var j = 0, jn = col.length; j < jn; j++)
{
if(!rows[j]) rows[j] = [];
rows[j].push(col[j]);
}
}
return rows;
}
function logRow(ops, buffer)
{
console.log(cli.utils.repeat(' ', ops.pad.left) + buffer);
}
function drawBreak(ops)
{
if(ops.horz) logRow(ops, cli.utils.repeat(ops.horz, ops.width));
}
function drawRow(lineTable, ops)
{
for(var i = 0, n = lineTable.length; i < n; i++)
{
logRow(ops, lineTable[i].join(ops.vert))
}
drawBreak(ops);
}
function drawTable(source, ops)
{
if(ops.pad.top) console.log(cli.utils.repeat('\n', ops.pad.top-1));
drawBreak(ops);
for(var i = source.length; i--;)
{
var lineTable = getRowLineTable(source[i], ops)
drawRow(lineTable, ops);
}
if(ops.pad.bottom) console.log(cli.utils.repeat('\n', ops.pad.bottom-1));
}
cli.drawTable = function(source, ops)
{
ops = normalizeOptions(ops);
drawTable(source, ops);
// console.log(ops)
}
}