├── .gitignore ├── .npmignore ├── screenshot.gif ├── examples ├── random.sh └── sine.js ├── package.json ├── LICENSE.md ├── index.js └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .gitignore 2 | .npmignore 3 | screenshot.gif 4 | examples 5 | -------------------------------------------------------------------------------- /screenshot.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tabcorp/cli-plot/HEAD/screenshot.gif -------------------------------------------------------------------------------- /examples/random.sh: -------------------------------------------------------------------------------- 1 | for i in {1..50}; do 2 | echo $RANDOM; 3 | sleep 0.3; 4 | done 5 | -------------------------------------------------------------------------------- /examples/sine.js: -------------------------------------------------------------------------------- 1 | var i = 0; 2 | setInterval(function() { 3 | var value = Math.sin(i += 0.2); 4 | process.stdout.write(value + '\n'); 5 | }, 100); 6 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cli-plot", 3 | "version": "1.0.0", 4 | "description": "Plot values from stdin directly in your terminal", 5 | "author": "Tabcorp Digital Team", 6 | "license": "MIT", 7 | "main": "index.js", 8 | "bin": { 9 | "plot": "index.js" 10 | }, 11 | "dependencies": { 12 | "babar": "0.0.3", 13 | "charm": "~1.0.0", 14 | "fixedqueue": "0.0.1", 15 | "split": "~0.3.1", 16 | "optimist": "~0.6.1" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Tabcorp 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | var fixedQueue = require('fixedqueue').FixedQueue; 4 | var charm = require('charm')(); 5 | var babar = require('babar'); 6 | var split = require('split'); 7 | 8 | var cli = require('optimist') 9 | .usage('Plot values from stdin.\nUsage: $0 -w [width] -h [height]') 10 | .describe('w', 'Width of the chart (in terminal columns)') 11 | .describe('h', 'Height of the chart (in terminal rows)') 12 | .default({ w: 100, h: 10 }); 13 | 14 | if (cli.argv.help) { 15 | return cli.showHelp(); 16 | } 17 | 18 | var count = Math.floor(cli.argv.w / 3); 19 | var width = count * 3; 20 | var height = cli.argv.h; 21 | 22 | var first = true; 23 | var queue = fixedQueue(count); 24 | for (var i = 0; i < count; ++i) queue.push(0); 25 | 26 | function readValue(chunk) { 27 | var value = parseFloat(chunk); 28 | if (!isNaN(value)) { 29 | queue.enqueue(value); 30 | } 31 | } 32 | 33 | function plot() { 34 | var data = queue.map(function(value, index) { 35 | return [index + 1, value]; 36 | }); 37 | var max = queue.reduce(function(acc, val) { 38 | return (val > acc) ? val : acc; 39 | }, 0); 40 | var chart = babar(data, { 41 | color: 'green', 42 | width: width, 43 | height: height, 44 | yFractions: max > 10 ? 0 : 1 45 | }); 46 | if (!first) charm.up(height + 2); 47 | first = false; 48 | console.log('\n' + chart + '\n'); 49 | } 50 | 51 | charm.pipe(process.stdout); 52 | process.stdin.resume(); 53 | process.stdin.setEncoding('utf8'); 54 | 55 | process.stdin.pipe(split()).on('data', function(buffer) { 56 | readValue(buffer.toString()); 57 | plot(); 58 | }); 59 | 60 | process.stdin.on('end', function() { 61 | process.stdout.write('\n'); 62 | }); 63 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # cli-plot 2 | 3 | Plot values from `stdin` directly into your terminal. 4 | 5 | [![NPM](http://img.shields.io/npm/v/cli-plot.svg?style=flat)](https://npmjs.org/package/cli-plot) 6 | [![License](http://img.shields.io/npm/l/cli-plot.svg?style=flat)](https://github.com/TabDigital/cli-plot) 7 | [![Dependencies](http://img.shields.io/david/TabDigital/cli-plot.svg?style=flat)](https://david-dm.org/TabDigital/cli-plot) 8 | 9 | ``` 10 | npm install -g cli-plot 11 | ``` 12 | 13 | ## Usage 14 | 15 | Say you have the following shell script that outputs numbers on `stdout`: 16 | 17 | ```bash 18 | for i in {1..50}; do 19 | echo $RANDOM; 20 | sleep 1; 21 | done 22 | ``` 23 | 24 | Or the following `Node` program that outputs a sine wave: 25 | 26 | ```js 27 | var i = 0; 28 | setInterval(function() { 29 | var value = Math.sin(i += 0.2); 30 | process.stdout.write(value + '\n'); 31 | }, 100); 32 | ``` 33 | 34 | You can pipe it into `plot` to generate a chart right there in your terminal. 35 | It will push new values from the right every time they arrive on stdin. 36 | Note: input values must be separated by a new line. 37 | 38 | ```bash 39 | node sine.js | plot 40 | ``` 41 | 42 | ![Screenshot](https://raw.github.com/TabDigital/cli-plot/master/screenshot.gif) 43 | 44 | ## Arguments 45 | 46 | - `plot -w 100`: graph width (in terminal rows) 47 | - `plot -h 10`: graph height (in terminal rows) 48 | 49 | ## Advanced usage 50 | 51 | - Printing averages 52 | 53 | If the input program outputs numbers very often, the chart will probably move too fast. 54 | You can pipe the output into a tool like [cli-average](https://github.com/TabDigital/cli-average). 55 | 56 | ```bash 57 | ./random.sh | avg -t 1s | plot 58 | ``` 59 | 60 | - Watching the output of another program 61 | 62 | One common usage is to run a command at a given rate, and plot its results. 63 | 64 | Unfortunately, the `watch` command also outputs debug info and ANSI escape codes, 65 | which doesn't play well with `plot`. You'll need to use different way to watch that command, 66 | for example [cli-interval](https://github.com/TabDigital/cli-interval). 67 | 68 | ```bash 69 | interval -t 1s "echo \$RANDOM" | plot 70 | ``` 71 | 72 | - Getting values from JSON documents 73 | 74 | The easiest way is to use tools like [json](http://trentm.com/json/) or [jQ](http://stedolan.github.io/jq/). 75 | 76 | ```bash 77 | some_program | json "path.to.value" | plot 78 | ``` 79 | --------------------------------------------------------------------------------