Skip to content
Browse files

add input interface

  • Loading branch information...
1 parent 6cc69b5 commit b8ddd04d3fa1fb30126573916396b264ffdf763c @davepacheco committed Aug 6, 2012
Showing with 151 additions and 17 deletions.
  1. +19 −10 README.md
  2. +9 −0 examples/ex.input.js
  3. +13 −0 examples/ex.input_named.js
  4. +10 −0 examples/ex.input_ps.js
  5. +96 −5 lib/tab.js
  6. +4 −2 package.json
View
29 README.md
@@ -1,8 +1,5 @@
# node-tab: Unix-style tables for command-line utilities
-**Status**: This README describes what this module *will* be. It's not yet
-implemented.
-
This module implements functions for reading and writing Unix-style command line
tables. The model mimics that of traditional Unix commands like "ps", which
emit a table with a default set of columns that can be customized using command
@@ -164,11 +161,9 @@ To ingest streaming tabular input, create a TableInputStream and listen for the
'columns': [ 'pid', 'tty', 'time', 'cmd' ]
});
- input.on('row', function (row) {
- console.log(row);
- });
+ input.on('row', console.log);
-This would emit:
+For the above outputs, this would emit:
{ pid: '60881',
tty: 'ttys000',
@@ -179,12 +174,27 @@ This would emit:
time: '0:00.17',
cmd: 'vim README.md' }
+If the first row is the header row, you can leave off "columns":
+
+ var input = new mod_tab.TableInputStream({ 'stream': process.stdin });
+ input.on('row', console.log);
+
+Pipe "ps" to that and get:
+
+ { PID: '60881',
+ TTY: 'ttys000',
+ TIME: '0:00.19',
+ CMD: '-bash' }
+ { PID: '61674',
+ TTY: 'ttys000',
+ TIME: '0:00.17',
+ CMD: 'vim README.md' }
+
You could get arrays instead by specifying the 'format' property:
var input = new mod_tab.TableInputStream({
'format': 'array',
'stream': process.stdin,
- 'columns': [ 'pid', 'tty', 'time', 'cmd' ]
});
input.on('row', function (row) {
@@ -209,8 +219,7 @@ in:
/* split on semicolon or comma */
var input = new mod_tab.TableInputStream({
- 'delim': /,;/,
+ 'delim': /[,;]/,
'stream': process.stdin,
'columns': [ 'pid', 'tty', 'time', 'cmd' ]
});
-
View
9 examples/ex.input.js
@@ -0,0 +1,9 @@
+var mod_tab = require('../lib/tab');
+
+/*
+ * Given column names in the first row, this emits incoming rows as JSON. Try:
+ * $ ps | node examples/ex.input.js
+ */
+var input = new mod_tab.TableInputStream({ 'stream': process.stdin });
+input.on('row', console.log);
+process.stdin.resume();
View
13 examples/ex.input_named.js
@@ -0,0 +1,13 @@
+var mod_tab = require('../lib/tab');
+
+/*
+ * Given column names on stdin, this emits incoming rows as JSON. Try:
+ * $ ps | node examples/ex.input_named.js pid tty time cmd
+ */
+var input = new mod_tab.TableInputStream({
+ 'stream': process.stdin,
+ 'columns': process.argv.slice(2)
+});
+
+input.on('row', console.log);
+process.stdin.resume();
View
10 examples/ex.input_ps.js
@@ -0,0 +1,10 @@
+var mod_tab = require('../lib/tab');
+
+/* This example processes default "ps" output. */
+var input = new mod_tab.TableInputStream({
+ 'stream': process.stdin,
+ 'columns': [ 'pid', 'tty', 'time', 'cmd' ]
+});
+
+input.on('row', console.log);
+process.stdin.resume();
View
101 lib/tab.js
@@ -3,13 +3,24 @@
*/
var mod_assert = require('assert-plus');
+var mod_carrier = require('carrier');
+var mod_events = require('events');
var mod_extsprintf = require('extsprintf');
+var mod_strsplit = require('strsplit');
+var mod_util = require('util');
/* Public interface */
exports.emitTable = emitTable;
exports.TableOutputStream = TableOutputStream;
exports.TableInputStream = TableInputStream;
+function fprintf(stream)
+{
+ var args = Array.prototype.slice.call(arguments, 1);
+ var str = mod_extsprintf.sprintf.apply(null, args);
+ stream.write(str);
+}
+
/*
* Named arguments:
*
@@ -194,14 +205,94 @@ function emitTable(args)
args.rows.forEach(function (row) { stream.writeRow(row); });
}
+/*
+ * Stream tabular input. Arguments:
+ *
+ * stream Input stream (e.g., process.stdin)
+ *
+ * [columns] Array of column names
+ * Default: inferred from first line of input
+ *
+ * [noTrimStart] If true, leading whitespace is not trimmed from
+ * each row. Most Unix tools (e.g., awk, bash) do
+ * trim whitespace.
+ * Default: false
+ *
+ * [encoding] Text encoding
+ * Default: 'utf8'
+ *
+ * [columnSeparator] String or regex for splitting columns.
+ * Default: /\s+/
+ *
+ * [rowSeparator] String or regex for splitting rows
+ * Default: '\n'
+ *
+ * [format] Format of emitted records ('object' | 'array')
+ * Default: 'object'
+ */
function TableInputStream(args)
{
+ mod_assert.object(args);
+ mod_assert.object(args.stream);
+
+ mod_assert.optionalString(args.format);
+ if (args.format) {
+ mod_assert.ok(args.format == 'array' ||
+ args.format == 'object');
+ }
+
+ if (args.columns)
+ this.tis_cols = args.columns.slice(0);
+ this.tis_notrim = args.noTrimStart || false;
+ this.tis_stream = args.stream;
+ this.tis_encoding = args.encoding || 'utf8';
+ this.tis_colsep = args.columnSeparator;
+ if (!this.tis_colsep)
+ this.tis_colsep = /\s+/;
+
+ if (!(this.tis_colsep instanceof RegExp))
+ this.tis_colsep = new RegExp(this.tis_colsep);
+
+ this.tis_rowsep = args.rowSeparator || '\n';
+ this.tis_format = args.format || 'object';
+ this.tis_carrier = mod_carrier.carry(this.tis_stream,
+ this.onLine.bind(this), this.tis_encoding, this.tis_rowsep);
+
+ this.tis_stream.on('close', this.emit.bind(this));
+ this.tis_stream.on('end', this.emit.bind(this));
+ this.tis_stream.on('error', this.emit.bind(this));
+
+ mod_events.EventEmitter();
}
-function fprintf(stream)
+mod_util.inherits(TableInputStream, mod_events.EventEmitter);
+
+TableInputStream.prototype.onLine = function (line)
{
- var args = Array.prototype.slice.call(arguments, 1);
- var str = mod_extsprintf.sprintf.apply(null, args);
- stream.write(str);
-}
+ var parts, rv, i;
+
+ if (!this.tis_notrim)
+ line = line.replace(/^\s+/, '');
+
+ if (!this.tis_cols) {
+ this.tis_cols = mod_strsplit(line, this.tis_colsep);
+ return;
+ }
+
+ parts = mod_strsplit(line, this.tis_colsep, this.tis_cols.length);
+
+ for (i = parts.length; i < this.tis_cols.length; i++)
+ parts.push('');
+
+ if (this.tis_format == 'array') {
+ this.emit('row', parts);
+ return;
+ }
+
+ rv = {};
+ for (i = 0; i < this.tis_cols.length; i++)
+ rv[this.tis_cols[i]] = parts[i];
+
+ this.emit('row', rv);
+};
View
6 package.json
@@ -1,6 +1,6 @@
{
"name": "tab",
- "version": "0.0.2",
+ "version": "0.1.0",
"description": "Unix-style tables for command-line utilities",
"main": "lib/tab.js",
"repository": {
@@ -12,6 +12,8 @@
"license": "MIT",
"dependencies": {
"assert-plus": "0.1.0",
- "extsprintf": "1.0.1"
+ "carrier": "0.1.7",
+ "extsprintf": "1.0.1",
+ "strsplit": "1.0.0"
}
}

0 comments on commit b8ddd04

Please sign in to comment.
Something went wrong with that request. Please try again.