The response has been limited to 50k tokens of the smallest files in the repo. You can remove this limitation by removing the max tokens filter.
├── .eslintrc.json
├── .gitignore
├── .npmignore
├── LICENSE.md
├── README.md
├── docs
    ├── fonts
    │   └── freemono.zip
    └── images
    │   ├── bar.gif
    │   ├── dashboard.png
    │   ├── donut.gif
    │   ├── gauge.gif
    │   ├── lcd.gif
    │   ├── line.gif
    │   ├── log.gif
    │   ├── map.gif
    │   ├── markdown.png
    │   ├── picture.png
    │   ├── spark.gif
    │   ├── stacked-bar.png
    │   ├── stackgauge.gif
    │   ├── table.gif
    │   ├── term3.gif
    │   ├── tree.gif
    │   └── truload.png
├── examples
    ├── bar.js
    ├── carousel.js
    ├── dashboard-random-colors.js
    ├── dashboard.js
    ├── donut.js
    ├── explorer.js
    ├── gauge-list.js
    ├── gauge-stack.js
    ├── gauge.js
    ├── grid-no-border.js
    ├── grid.js
    ├── inline-data
    │   ├── bar.js
    │   ├── donut.js
    │   ├── gauge.js
    │   ├── lcd.js
    │   ├── map.js
    │   ├── markdown.js
    │   ├── multi-line-chart.js
    │   ├── picture.js
    │   ├── sparkline.js
    │   └── table.js
    ├── lcd.js
    ├── line-abbreviate.js
    ├── line-fraction.js
    ├── line-random-colors.js
    ├── line-start-above-zero.js
    ├── line-zoomed-in.js
    ├── log.js
    ├── map.js
    ├── markdown.js
    ├── marked-terminal.js
    ├── media
    │   └── flower.png
    ├── multi-line-chart.js
    ├── picture.js
    ├── sparkline.js
    ├── stacked-bar.js
    ├── table-color.js
    └── table.js
├── index.d.ts
├── index.js
├── lib
    ├── layout
    │   ├── carousel.js
    │   └── grid.js
    ├── server-utils.js
    ├── utils.js
    └── widget
    │   ├── canvas.js
    │   ├── charts
    │       ├── bar.js
    │       ├── line.js
    │       └── stacked-bar.js
    │   ├── donut.js
    │   ├── gauge-list.js
    │   ├── gauge.js
    │   ├── lcd.js
    │   ├── log.js
    │   ├── map.js
    │   ├── markdown.js
    │   ├── picture.js
    │   ├── sparkline.js
    │   ├── table.js
    │   └── tree.js
├── package-lock.json
└── package.json


/.eslintrc.json:
--------------------------------------------------------------------------------
 1 | {
 2 |   "env": {
 3 |     "es6": true,
 4 |     "node": true
 5 |   },
 6 |   "extends": "eslint:recommended",
 7 |   "parserOptions": {
 8 |     "ecmaVersion": 2015
 9 |   },
10 |   "rules": {
11 |     "brace-style": "error",
12 |     "no-irregular-whitespace":"error",
13 |     "no-octal-escape": "error",
14 |     "no-octal": "error",
15 |     "no-proto":"error",
16 |     "strict":["error", "global"],
17 |     "no-undef":"error",
18 |     "no-use-before-define": "off",
19 |     "indent": ["error", 2],
20 |     "semi": [2, "always"],
21 |     "quotes": [2, "single"]
22 |   }
23 | }
24 | 


--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .dccache
2 | node_modules
3 | p.js
4 | p1.js
5 | p2.js
6 | npm-debug.log
7 | log.txt
8 | weather.query
9 | 


--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | p.js
3 | p1.js
4 | p2.js
5 | npm-debug.log
6 | docs
7 | examples


--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
 1 | ## MIT License
 2 | 
 3 | Copyright (c) 2015 Yaron Naveh and blessed-contrib contributors
 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 | 


--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
  1 | ## blessed-contrib
  2 | 
  3 | Build dashboards (or any other application) using ascii/ansi art and javascript.
  4 | 
  5 | Friendly to terminals, ssh and developers. Extends [blessed](https://github.com/chjj/blessed) with custom  [drawille](https://github.com/madbence/node-drawille) and other widgets.
  6 | 
  7 | You should also [check WOPR](https://github.com/yaronn/wopr): a markup for creating terminal reports, presentations and infographics.
  8 | 
  9 | 
 10 | **Contributors:**
 11 | 
 12 | Yaron Naveh ([@YaronNaveh](http://twitter.com/YaronNaveh))
 13 | Chris ([@xcezzz](https://twitter.com/xcezzz))
 14 | Miguel Valadas ([@mvaladas](https://github.com/mvaladas))
 15 | Liran Tal ([@lirantal](https://github.com/lirantal))
 16 | 
 17 | **Demo ([full size](https://raw.githubusercontent.com/yaronn/blessed-contrib/master/docs/images/term3.gif)):**
 18 | 
 19 | <img src="./docs/images/truload.png" alt="term" width="800">
 20 | 
 21 | <img src="./docs/images/term3.gif" alt="term" width="800">
 22 | 
 23 | ([source code](./examples/dashboard.js))
 24 | 
 25 | **Running the demo**
 26 | 
 27 |     git clone https://github.com/yaronn/blessed-contrib.git
 28 |     cd blessed-contrib
 29 |     npm install
 30 |     node ./examples/dashboard.js
 31 | 
 32 | Works on Linux, OS X and Windows. For Windows follow the [pre requisites](http://webservices20.blogspot.co.il/2015/04/running-terminal-dashboards-on-windows.html).
 33 | 
 34 | ## Installation (to build custom projects)
 35 | 
 36 |     npm install blessed blessed-contrib
 37 | 
 38 | ## Usage
 39 | 
 40 | You can use any of the default widgets of [blessed](https://github.com/chjj/blessed) (texts, lists and etc) or the widgets added in blessed-contrib (described below). A [layout](#layouts) is optional but useful for dashboards. The widgets in blessed-contrib follow the same usage pattern:
 41 | 
 42 | `````javascript
 43 |    var blessed = require('blessed')
 44 |      , contrib = require('blessed-contrib')
 45 |      , screen = blessed.screen()
 46 |      , line = contrib.line(
 47 |          { style:
 48 |            { line: "yellow"
 49 |            , text: "green"
 50 |            , baseline: "black"}
 51 |          , xLabelPadding: 3
 52 |          , xPadding: 5
 53 |          , label: 'Title'})
 54 |      , data = {
 55 |          x: ['t1', 't2', 't3', 't4'],
 56 |          y: [5, 1, 7, 5]
 57 |       }
 58 |    screen.append(line) //must append before setting data
 59 |    line.setData([data])
 60 | 
 61 |    screen.key(['escape', 'q', 'C-c'], function(ch, key) {
 62 |      return process.exit(0);
 63 |    });
 64 | 
 65 |    screen.render()
 66 | `````
 67 | 
 68 | See below for a complete list of widgets.
 69 | 
 70 | 
 71 | ## Widgets
 72 | 
 73 | [Line Chart](#line-chart)
 74 | 
 75 | [Bar Chart](#bar-chart)
 76 | 
 77 | [Stacked Bar Chart](#stacked-bar-chart)
 78 | 
 79 | [Map](#map)
 80 | 
 81 | [Gauge](#gauge)
 82 | 
 83 | [Stacked Gauge](#stacked-gauge)
 84 | 
 85 | [Donut](#donut)
 86 | 
 87 | [LCD Display](#lcd-display)
 88 | 
 89 | [Rolling Log](#rolling-log)
 90 | 
 91 | [Picture](#picture)
 92 | 
 93 | [Sparkline](#sparkline)
 94 | 
 95 | [Table](#table)
 96 | 
 97 | [Tree](#tree)
 98 | 
 99 | [Markdown](#markdown)
100 | 
101 | ### Line Chart
102 | 
103 | <img src="./docs/images/line.gif" alt="line" width="400">
104 | 
105 | `````javascript
106 |    var line = contrib.line(
107 |          { style:
108 |            { line: "yellow"
109 |            , text: "green"
110 |            , baseline: "black"}
111 |          , xLabelPadding: 3
112 |          , xPadding: 5
113 |          , showLegend: true
114 |          , wholeNumbersOnly: false //true=do not show fraction in y axis
115 |          , label: 'Title'})
116 |    var series1 = {
117 |          title: 'apples',
118 |          x: ['t1', 't2', 't3', 't4'],
119 |          y: [5, 1, 7, 5]
120 |       }
121 |    var series2 = {
122 |          title: 'oranges',
123 |          x: ['t1', 't2', 't3', 't4'],
124 |          y: [2, 1, 4, 8]
125 |       }
126 |    screen.append(line) //must append before setting data
127 |    line.setData([series1, series2])
128 | `````
129 | **Examples:** [simple line chart](./examples/line-fraction.js), [multiple lines](./examples/multi-line-chart.js), [256 colors](./examples/line-random-colors.js)
130 | 
131 | ### Bar Chart
132 | 
133 | <img src="./docs/images/bar.gif" alt="bar" width="250">
134 | 
135 | `````javascript
136 |     var bar = contrib.bar(
137 |        { label: 'Server Utilization (%)'
138 |        , barWidth: 4
139 |        , barSpacing: 6
140 |        , xOffset: 0
141 |        , maxHeight: 9})
142 |     screen.append(bar) //must append before setting data
143 |     bar.setData(
144 |        { titles: ['bar1', 'bar2']
145 |        , data: [5, 10]})
146 | `````
147 | 
148 | ### Stacked Bar Chart
149 | 
150 | <img src="./docs/images/stacked-bar.png" alt="stacked-bar" width="250">
151 | 
152 | `````javascript
153 |     bar = contrib.stackedBar(
154 |        { label: 'Server Utilization (%)'
155 |        , barWidth: 4
156 |        , barSpacing: 6
157 |        , xOffset: 0
158 |        //, maxValue: 15
159 |        , height: "40%"
160 |        , width: "50%"
161 |        , barBgColor: [ 'red', 'blue', 'green' ]})
162 |     screen.append(bar)
163 |     bar.setData(
164 |        { barCategory: ['Q1', 'Q2', 'Q3', 'Q4']
165 |        , stackedCategory: ['US', 'EU', 'AP']
166 |        , data:
167 |           [ [ 7, 7, 5]
168 |           , [8, 2, 0]
169 |           , [0, 0, 0]
170 |           , [2, 3, 2] ]
171 |        })
172 | `````
173 | 
174 | ### Map
175 | 
176 | <img src="./docs/images/map.gif" alt="map" width="500">
177 | 
178 | `````javascript
179 |    var map = contrib.map({label: 'World Map'})
180 |    map.addMarker({"lon" : "-79.0000", "lat" : "37.5000", color: "red", char: "X" })
181 | `````
182 | 
183 | 
184 | ### Gauge
185 | 
186 | <img src="./docs/images/gauge.gif" alt="gauge" width="170">
187 | 
188 | `````javascript
189 |    var gauge = contrib.gauge({label: 'Progress', stroke: 'green', fill: 'white'})
190 |    gauge.setPercent(25)
191 | `````
192 | 
193 | ### Stacked Gauge
194 | 
195 | <img src="./docs/images/stackgauge.gif" alt="stackedgauge">
196 | 
197 | Either specify each stacked portion with a `percent` and `stroke`...
198 | 
199 | `````javascript
200 |    var gauge = contrib.gauge({label: 'Stacked '})
201 |    gauge.setStack([{percent: 30, stroke: 'green'}, {percent: 30, stroke: 'magenta'}, {percent: 40, stroke: 'cyan'}])
202 | `````
203 | 
204 | Or, you can just supply an array of numbers and random colors will be chosen.
205 | 
206 | `````javascript
207 |    var gauge = contrib.gauge({label: 'Stacked Progress'})
208 |    gauge.setStack([30,30,40])
209 | `````
210 | 
211 | ### Donut
212 | 
213 | <img src="./docs/images/donut.gif" alt="donut">
214 | 
215 | 
216 | `````javascript
217 |    var donut = contrib.donut({
218 | 	label: 'Test',
219 | 	radius: 8,
220 | 	arcWidth: 3,
221 | 	remainColor: 'black',
222 | 	yPadding: 2,
223 | 	data: [
224 | 	  {percent: 80, label: 'web1', color: 'green'}
225 | 	]
226 |   });
227 | `````
228 | 
229 | Data passed in uses `percent` and `label` to draw the donut graph. Color is optional and defaults to green.
230 | 
231 | `````javascript
232 |    donut.setData([
233 |    	{percent: 87, label: 'rcp','color': 'green'},
234 | 	{percent: 43, label: 'rcp','color': 'cyan'},
235 |    ]);
236 | `````
237 | 
238 | Updating the donut is as easy as passing in an array to `setData` using the same array format as in the constructor. Pass in as many objects to the array of data as you want, they will automatically resize and try to fit. However, please note that you will still be restricted to actual screen space.
239 | 
240 | You can also hardcode a specific numeric into the donut's core display instead of the percentage by passing an `percentAltNumber` property to the data, such as:
241 | 
242 | `````javascript
243 |    var donut = contrib.donut({
244 | 	label: 'Test',
245 | 	radius: 8,
246 | 	arcWidth: 3,
247 | 	remainColor: 'black',
248 | 	yPadding: 2,
249 | 	data: [
250 | 	  {percentAltNumber: 50, percent: 80, label: 'web1', color: 'green'}
251 | 	]
252 |   });
253 | `````
254 | 
255 | See an example of this in one of the donuts settings on `./examples/donut.js`.
256 | 
257 | ### LCD Display
258 | 
259 | <img src="./docs/images/lcd.gif" alt="lcd">
260 | 
261 | `````javascript
262 |    var lcd = contrib.lcd(
263 |      { segmentWidth: 0.06 // how wide are the segments in % so 50% = 0.5
264 |      , segmentInterval: 0.11 // spacing between the segments in % so 50% = 0.550% = 0.5
265 |      , strokeWidth: 0.11 // spacing between the segments in % so 50% = 0.5
266 |      , elements: 4 // how many elements in the display. or how many characters can be displayed.
267 |      , display: 321 // what should be displayed before first call to setDisplay
268 |      , elementSpacing: 4 // spacing between each element
269 |      , elementPadding: 2 // how far away from the edges to put the elements
270 |      , color: 'white' // color for the segments
271 |      , label: 'Storage Remaining'})
272 | `````
273 | 
274 | `````javascript
275 | 
276 | 	lcd.setDisplay(23 + 'G'); // will display "23G"
277 | 	lcd.setOptions({}) // adjust options at runtime
278 | 
279 | `````
280 | 
281 | Please see the **examples/lcd.js** for an example. The example provides keybindings to adjust the `segmentWidth` and `segmentInterval` and `strokeWidth` in real-time so that you can see how they manipulate the look and feel.
282 | 
283 | 
284 | ### Rolling Log
285 | 
286 | <img src="./docs/images/log.gif" alt="log" width="180">
287 | 
288 | `````javascript
289 |    var log = contrib.log(
290 |       { fg: "green"
291 |       , selectedFg: "green"
292 |       , label: 'Server Log'})
293 |    log.log("new log line")
294 | `````
295 | 
296 | 
297 | ### Picture
298 | 
299 | (Also check the new blessed [image implementation](https://github.com/chjj/blessed#image-from-box) which has several benefits over this one.)
300 | 
301 | <img src="./docs/images/picture.png" alt="log" width="180">
302 | 
303 | `````javascript
304 |     var pic = contrib.picture(
305 |        { file: './flower.png'
306 |        , cols: 25
307 |        , onReady: ready})
308 |     function ready() {screen.render()}
309 | `````
310 | 
311 | note: only png images are supported
312 | 
313 | 
314 | ### Sparkline
315 | 
316 | <img src="./docs/images/spark.gif" alt="spark" width="180">
317 | 
318 | `````javascript
319 |    var spark = contrib.sparkline(
320 |      { label: 'Throughput (bits/sec)'
321 |      , tags: true
322 |      , style: { fg: 'blue' }})
323 | 
324 |    sparkline.setData(
325 |    [ 'Sparkline1', 'Sparkline2'],
326 |    [ [10, 20, 30, 20]
327 |    , [40, 10, 40, 50]])
328 | `````
329 | 
330 | ### Table
331 | 
332 | <img src="./docs/images/table.gif" alt="table" width="250">
333 | 
334 | `````javascript
335 |    var table = contrib.table(
336 |      { keys: true
337 |      , fg: 'white'
338 |      , selectedFg: 'white'
339 |      , selectedBg: 'blue'
340 |      , interactive: true
341 |      , label: 'Active Processes'
342 |      , width: '30%'
343 |      , height: '30%'
344 |      , border: {type: "line", fg: "cyan"}
345 |      , columnSpacing: 10 //in chars
346 |      , columnWidth: [16, 12, 12] /*in chars*/ })
347 | 
348 |    //allow control the table with the keyboard
349 |    table.focus()
350 | 
351 |    table.setData(
352 |    { headers: ['col1', 'col2', 'col3']
353 |    , data:
354 |       [ [1, 2, 3]
355 |       , [4, 5, 6] ]})
356 | `````
357 | 
358 | ### Tree
359 | 
360 | <img src="./docs/images/tree.gif" alt="table" width="250">
361 | 
362 | `````javascript
363 |    var tree = contrib.tree({fg: 'green'})
364 | 
365 |    //allow control the table with the keyboard
366 |    tree.focus()
367 | 
368 |    tree.on('select',function(node){
369 |      if (node.myCustomProperty){
370 |        console.log(node.myCustomProperty);
371 |      }
372 |      console.log(node.name);
373 |    }
374 | 
375 |    // you can specify a name property at root level to display root
376 |    tree.setData(
377 |    { extended: true
378 |    , children:
379 |      {
380 |        'Fruit':
381 |        { children:
382 |          { 'Banana': {}
383 |          , 'Apple': {}
384 |          , 'Cherry': {}
385 |          , 'Exotics': {
386 |              children:
387 |              { 'Mango': {}
388 |              , 'Papaya': {}
389 |              , 'Kiwi': { name: 'Kiwi (not the bird!)', myCustomProperty: "hairy fruit" }
390 |              }}
391 |          , 'Pear': {}}}
392 |      , 'Vegetables':
393 |        { children:
394 |          { 'Peas': {}
395 |          , 'Lettuce': {}
396 |          , 'Pepper': {}}}}})
397 | `````
398 | 
399 | #### Options
400 | 
401 |  * keys : Key to expand nodes. Default : ['enter','default']
402 |  * extended : Should nodes be extended/generated by default? Be careful with this setting when using a callback function. Default : false
403 |  * template :
404 |    * extend : Suffix "icon" for closed node. Default : '[+]'
405 |    * retract : Suffix "icon" for opened node. Default : '[-]'
406 |    * lines : Show lines in tree. Default : true
407 | 
408 | #### Nodes
409 | 
410 | Every node is a hash and it can have custom properties that can be used in "select" event callback. However, there are several special keys :
411 | 
412 | * name
413 |   * *Type* : `string`
414 |   * *Desc* : Node name
415 |   * If the node isn't the root and you don't specify the name, will be set to hash key
416 |   * *Example* : <code>{ name: 'Fruit'}</code>
417 | * children
418 |   * *Type* : `hash` or `function(node){ return children }`
419 |   * *Desc* : Node children.
420 |   * The function must return a hash that could have been used as children property
421 |   * If you use a function, the result will be stored in `node.childrenContent` and `children`
422 |   * *Example* :
423 |     * Hash : <code>{'Fruit':{ name: 'Fruit', children:{ 'Banana': {}, 'Cherry': {}}}}</code>
424 |     * Function : see `examples/explorer.js`
425 | * childrenContent
426 |   * *Type* : `hash`
427 |   * *Desc* : Children content for internal usage *DO NOT MODIFY*
428 |   * If `node.children` is a hash, `node.children===node.childrenContent`
429 |   * If `node.children` is a function, it's used to store the `node.children()` result
430 |   * You can read this property, but you should never write it.
431 |   * Usually this will be used to check `if(node.childrenContent)` in your `node.children` function to generate children only once
432 | * extended
433 |   * *Type* : `boolean`
434 |   * *Desc* : Determine if this node is extended
435 |   * No effect when the node have no child
436 |   * Default value for each node will be `treeInstance.options.extended` if the node `extended` option is not set
437 |   * *Example* : <code>{'Fruit':{ name: 'Fruit', extended: true, children:{ 'Banana': {}, 'Cherry': {}}}}</code>
438 | 
439 | ### Markdown
440 | 
441 | <img src="./docs/images/markdown.png" alt="table">
442 | 
443 | `````javascript
444 |    var markdown = contrib.markdown()
445 |    markdown.setMarkdown('# Hello \n blessed-contrib renders markdown using `marked-terminal`')
446 | `````
447 | 
448 | ### Colors
449 | You can use 256 colors ([source](./examples/line-random-colors.js)):
450 | 
451 | `````javascript
452 |   function randomColor() {
453 |     return [Math.random() * 255,Math.random()*255, Math.random()*255]
454 |   }
455 | 
456 |   line = contrib.line(
457 |   {
458 |     ...
459 |     , style: { line: randomColor(), text: randomColor(), baseline: randomColor() }
460 |   })
461 | `````
462 |    
463 | ### Layouts
464 | 
465 | [Grid](#grid)
466 | 
467 | [Carousel](#carousel)
468 | 
469 | ### Grid
470 | 
471 | A grid layout can auto position your elements in a grid layout.
472 | When using a grid, you should not create the widgets, rather specify to the grid which widget to create and with which params.
473 | Each widget can span multiple rows and columns.
474 | 
475 | `````javascript
476 |    var screen = blessed.screen()
477 | 
478 |    var grid = new contrib.grid({rows: 12, cols: 12, screen: screen})
479 | 
480 |    //grid.set(row, col, rowSpan, colSpan, obj, opts)
481 |    var map = grid.set(0, 0, 4, 4, contrib.map, {label: 'World Map'})
482 |    var box = grid.set(4, 4, 4, 4, blessed.box, {content: 'My Box'})
483 | 
484 |    screen.render()
485 | `````
486 | 
487 | ### Carousel
488 | A carousel layout switches between different views based on time or keyboard activity.
489 | One use case is an office dashboard with rotating views:
490 | 
491 | `````javascript
492 |     var blessed = require('blessed')
493 |       , contrib = require('./')
494 |       , screen = blessed.screen()
495 | 
496 |     function page1(screen) {
497 |        var map = contrib.map()
498 |        screen.append(map)
499 |     }
500 | 
501 |     function page2(screen) {
502 |       var line = contrib.line(
503 |        { width: 80
504 |        , height: 30
505 |        , left: 15
506 |        , top: 12
507 |        , xPadding: 5
508 |        , label: 'Title'
509 |        })
510 | 
511 |       var data = [ { title: 'us-east',
512 |                  x: ['t1', 't2', 't3', 't4'],
513 |                  y: [0, 0.0695652173913043, 0.11304347826087, 2],
514 |                  style: {
515 |                   line: 'red'
516 |                  }
517 |                }
518 |             ]
519 | 
520 |       screen.append(line)
521 |       line.setData(data)
522 |     }
523 | 
524 |     screen.key(['escape', 'q', 'C-c'], function(ch, key) {
525 |       return process.exit(0);
526 |     });
527 | 
528 |     var carousel = new contrib.carousel( [page1, page2]
529 |                                        , { screen: screen
530 |                                          , interval: 3000 //how often to switch views (set 0 to never swicth automatically)
531 |                                          , controlKeys: true  //should right and left keyboard arrows control view rotation
532 |                                          })
533 |     carousel.start()
534 | 
535 | `````
536 | 
537 | ## Samples
538 | 
539 | 
540 | ### Terminal Dashboard
541 | 
542 | <img src="./docs/images/term3.gif" alt="term" width="800">
543 | 
544 | **Running the sample**
545 | 
546 |     git clone https://github.com/yaronn/blessed-contrib.git
547 |     cd blessed-contrib
548 |     npm install
549 |     node ./examples/dashboard.js
550 | 
551 | **Installation (for a custom dashboard)**
552 | 
553 |     npm install blessed
554 |     npm install blessed-contrib
555 | 
556 | 
557 | **A simple dashboard**
558 | 
559 | `````javascript
560 |    var blessed = require('blessed')
561 |      , contrib = require('blessed-contrib')
562 |      , screen = blessed.screen()
563 |      , grid = new contrib.grid({rows: 1, cols: 2, screen: screen})
564 | 
565 |    var line = grid.set(0, 0, 1, 1, contrib.line,
566 |      { style:
567 |        { line: "yellow"
568 |        , text: "green"
569 |        , baseline: "black"}
570 |      , xLabelPadding: 3
571 |      , xPadding: 5
572 |      , label: 'Stocks'})
573 | 
574 |    var map = grid.set(0, 1, 1, 1, contrib.map, {label: 'Servers Location'})
575 | 
576 |    var lineData = {
577 |       x: ['t1', 't2', 't3', 't4'],
578 |       y: [5, 1, 7, 5]
579 |    }
580 | 
581 |    line.setData([lineData])
582 | 
583 |    screen.key(['escape', 'q', 'C-c'], function(ch, key) {
584 |      return process.exit(0);
585 |    });
586 | 
587 |    screen.render()
588 | `````
589 | 
590 | **Rich dashboard**
591 | 
592 | See [source code](./examples/dashboard.js)
593 | 
594 | ## Troubleshooting
595 | If you see questions marks or some (or all) missign characters try running with these env vars to fix encoding / terminal: 
596 | `````
597 |     
gt; LANG=en_US.utf8 TERM=xterm-256color node your-code.js 
598 | `````
599 | 
600 | ## License
601 | This library is under the [MIT License](http://opensource.org/licenses/MIT)
602 | 
603 | ## More Information
604 | Created by Yaron Naveh ([twitter](http://twitter.com/YaronNaveh), [blog](http://webservices20.blogspot.com/))
605 | 


--------------------------------------------------------------------------------
/docs/fonts/freemono.zip:
--------------------------------------------------------------------------------
  1 | <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  2 |     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  3 | <html xmlns="http://www.w3.org/1999/xhtml">
  4 | <head>
  5 |     <title>Font download</title>
  6 |     <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
  7 |     <meta http-equiv="Content-Language" content="en-US" />
  8 |     <meta name="description" content="Fonts2u offers a large collection of free fonts. Download free fonts for Windows and Macintosh." /><meta name="keywords" content="free fonts, download fonts, fonts, free, font, typefaces, typography, typeface, true type, truetype fonts, opentype, opentype fonts, windows, windows fonts, macintosh, mac fonts, macintosh fonts" />        <link rel="stylesheet" href="http://gzip.fonts2u.com/css/style-3-4-2015.css" type="text/css"/>
  9 |         
 10 | <script>
 11 | 
 12 |   (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
 13 |   (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
 14 |   m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
 15 |   })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
 16 |   ga('create', 'UA-563416-8', 'auto');
 17 |   ga('send', 'pageview');
 18 | </script></head>
 19 | 
 20 | <body>
 21 | 
 22 | <div id="min"></div>
 23 | 
 24 | <div id="page">
 25 | 	
 26 | <!-- Header start -->
 27 | <div id="header">
 28 | 	    <div id="tmenu">     
 29 | 					<div id="login">
 30 |   <a href="/login.html">Sign in</a> |
 31 |   <a href="/register.html">Register</a>
 32 | </div>
 33 | 					<div id="languages">
 34 | 	<ul>
 35 | <li class="bld"><span>English</span></li>
 36 | <li><a href="http://de.fonts2u.com/download/free-monospaced.schriftart">Deutsch</a></li>
 37 | <li><a href="http://fr.fonts2u.com/download/free-monospaced.police">Français</a></li>
 38 | <li><a href="http://es.fonts2u.com/download/free-monospaced.fuente">Español</a></li>
 39 | <li><a href="http://pt.fonts2u.com/download/free-monospaced.fonte">Português</a></li>
 40 | <li><a href="http://it.fonts2u.com/download/free-monospaced.carattere">Italiano</a></li>
 41 | <li><a href="http://pl.fonts2u.com/download/free-monospaced.czcionka">Polski</a></li>
 42 | <li><a href="http://cs.fonts2u.com/download/free-monospaced.písmo">Česky</a></li>
 43 | <li><a href="http://sk.fonts2u.com/download/free-monospaced.font">Slovensky</a></li>
 44 | <li><a href="http://ru.fonts2u.com/download/free-monospaced.шрифт">Pусский</a></li>
 45 | <li><a href="http://ua.fonts2u.com/download/free-monospaced.шрифт">Українська</a></li>
 46 | <li><a href="http://ja.fonts2u.com/download/free-monospaced.フォント">日本語</a></li>
 47 | <li><a href="http://zh.fonts2u.com/download/free-monospaced.字体">中文</a></li>
 48 | <li><a href="http://ar.fonts2u.com/download/free-monospaced.الخط">العربية</a></li>
 49 | </ul>
 50 | </div>
 51 | 					<div class="clr"></div>
 52 | 	    </div>
 53 | 
 54 | 	    <div id="logo">
 55 | 		<div class="logoleft"><a href="/index.html"><img src="http://nogzip.fonts2u.com/images/fonts2u_logo.gif" width="250" height="69" alt="logo" /></a>
 56 | 			<span id="fbook"></span>
 57 | 		</div>
 58 | 		<div id="bannertop"></div>
 59 | 	    </div>
 60 | 
 61 | 	    <div class="typesearch">
 62 | 		<div class="letters">
 63 |                         <a href="/letter.html?q=A">A</a>
 64 |                         <a href="/letter.html?q=B">B</a>
 65 |                         <a href="/letter.html?q=C">C</a>
 66 |                         <a href="/letter.html?q=D">D</a>
 67 |                         <a href="/letter.html?q=E">E</a>
 68 |                         <a href="/letter.html?q=F">F</a>
 69 |                         <a href="/letter.html?q=G">G</a>
 70 |                         <a href="/letter.html?q=H">H</a>
 71 |                         <a href="/letter.html?q=I">I</a>
 72 |                         <a href="/letter.html?q=J">J</a>
 73 |                         <a href="/letter.html?q=K">K</a>
 74 |                         <a href="/letter.html?q=L">L</a>
 75 |                         <a href="/letter.html?q=M">M</a>
 76 |                         <a href="/letter.html?q=N">N</a>
 77 |                         <a href="/letter.html?q=O">O</a>
 78 |                         <a href="/letter.html?q=P">P</a>
 79 |                         <a href="/letter.html?q=Q">Q</a>
 80 |                         <a href="/letter.html?q=R">R</a>
 81 |                         <a href="/letter.html?q=S">S</a>
 82 |                         <a href="/letter.html?q=T">T</a>
 83 |                         <a href="/letter.html?q=U">U</a>
 84 |                         <a href="/letter.html?q=V">V</a>
 85 |                         <a href="/letter.html?q=W">W</a>
 86 |                         <a href="/letter.html?q=X">X</a>
 87 |                         <a href="/letter.html?q=Y">Y</a>
 88 |                         <a href="/letter.html?q=Z">Z</a>
 89 |                         <a href="/letter.html?q=%23">#</a>
 90 | 		</div>
 91 | 
 92 | 		<div class="srchdiv">
 93 | 	      		<form action="/search.html" method="get">
 94 | 				<input name="q" size="25" />
 95 | 				<input type="submit" value="Search" />
 96 | 			</form>
 97 | 		</div>
 98 | 	    </div>
 99 | 	    <div class="clr"></div>
100 | </div>
101 | <!-- Header end -->
102 | 
103 | <div id="banner"></div>
104 | 
105 | <div>
106 | <ul id="tm">
107 |             <li><a href="/new-fonts.html">New fonts</a></li>
108 |             <li><a href="/top-rated-fonts.html">Top rated fonts</a></li>
109 |             <li><a href="/top-downloads.html">Top downloads</a></li>
110 |             <li><a href="/font-designers.html">Font designers</a></li>
111 |             <li><a href="/font-vendors.html">Font vendors</a></li>
112 |             <li><a href="/tools.html">Tools</a></li>
113 |             <li><a href="/submit_font.html"  class="but1">Submit font</a></li>
114 |             <li><a href="/font-converter.html" class="but1">Font converter</a></li>
115 | 
116 | 	    <div class="cl"></div>
117 | 
118 | </ul>
119 | </div>
120 | 	
121 | <!-- Navigation start -->
122 | <div id="nav">
123 | 
124 | 			<div class="navright">
125 | 				 <div id="menu">
126 | <ul >
127 | <li class="bld"><a href="/category.html?id=2">Basic</a></li>
128 | 	<li><a href="/category.html?id=18">Fixed width</a></li>
129 | 	<li><a href="/category.html?id=17">Monospace</a></li>
130 | 	<li><a href="/category.html?id=15">Sans serif</a></li>
131 | 	<li><a href="/category.html?id=16">Serif</a></li>
132 | 	<li><a href="/category.html?id=19">Various</a></li>
133 | 	<li class="active">&nbsp;</li>
134 | 	<li class="bld"><a href="/category.html?id=14">Bitmap</a></li>
135 | 	<li><a href="/category.html?id=60">Digital</a></li>
136 | 	<li><a href="/category.html?id=61">Pixelated</a></li>
137 | 	<li class="active">&nbsp;</li>
138 | 	<li class="bld"><a href="/category.html?id=3">Dingbats</a></li>
139 | 	<li><a href="/category.html?id=20">Alien</a></li></ul>
140 | 
141 | <ul >
142 | <li><a href="/category.html?id=23">Ancient</a></li>
143 | 	<li><a href="/category.html?id=21">Animals</a></li>
144 | 	<li><a href="/category.html?id=81">Art</a></li>
145 | 	<li><a href="/category.html?id=22">Asian</a></li>
146 | 	<li><a href="/category.html?id=70">Barcode</a></li>
147 | 	<li><a href="/category.html?id=84">Braille</a></li>
148 | 	<li><a href="/category.html?id=83">Cartoon</a></li>
149 | 	<li><a href="/category.html?id=25">Esoteric</a></li>
150 | 	<li><a href="/category.html?id=26">Fantastic</a></li>
151 | 	<li><a href="/category.html?id=78">Foods</a></li>
152 | 	<li><a href="/category.html?id=28">Games</a></li>
153 | 	<li><a href="/category.html?id=27">Horror</a></li>
154 | 	<li><a href="/category.html?id=69">Human</a></li></ul>
155 | 
156 | <ul >
157 | <li><a href="/category.html?id=75">Military</a></li>
158 | 	<li><a href="/category.html?id=77">Nature</a></li>
159 | 	<li><a href="/category.html?id=24">Runes</a></li>
160 | 	<li><a href="/category.html?id=79">Signs</a></li>
161 | 	<li><a href="/category.html?id=68">Sport</a></li>
162 | 	<li><a href="/category.html?id=71">Various</a></li>
163 | 	<li class="active">&nbsp;</li>
164 | 	<li class="bld"><a href="/category.html?id=5">Fancy</a></li>
165 | 	<li><a href="/category.html?id=65">3D</a></li>
166 | 	<li><a href="/category.html?id=35">Cartoon</a></li>
167 | 	<li><a href="/category.html?id=36">Comic</a></li>
168 | 	<li><a href="/category.html?id=39">Curly</a></li>
169 | 	<li><a href="/category.html?id=63">Digital</a></li></ul>
170 | 
171 | <ul >
172 | <li><a href="/category.html?id=42">Distorted</a></li>
173 | 	<li><a href="/category.html?id=41">Eroded</a></li>
174 | 	<li><a href="/category.html?id=59">Futuristic</a></li>
175 | 	<li><a href="/category.html?id=37">Groovy</a></li>
176 | 	<li><a href="/category.html?id=80">Military</a></li>
177 | 	<li><a href="/category.html?id=73">Modern</a></li>
178 | 	<li><a href="/category.html?id=62">Movies</a></li>
179 | 	<li><a href="/category.html?id=38">Old school</a></li>
180 | 	<li><a href="/category.html?id=64">Outlined</a></li>
181 | 	<li><a href="/category.html?id=67">Retro</a></li>
182 | 	<li><a href="/category.html?id=74">Scary</a></li>
183 | 	<li><a href="/category.html?id=58">Techno</a></li>
184 | 	<li><a href="/category.html?id=57">Various</a></li></ul>
185 | 
186 | <ul >
187 | <li><a href="/category.html?id=40">Western</a></li>
188 | 	<li class="active">&nbsp;</li>
189 | 	<li class="bld"><a href="/category.html?id=4">Foreign</a></li>
190 | 	<li><a href="/category.html?id=30">Arabic</a></li>
191 | 	<li><a href="/category.html?id=93">Bangla</a></li>
192 | 	<li><a href="/category.html?id=82">Burma</a></li>
193 | 	<li><a href="/category.html?id=97">Can Syllabics</a></li>
194 | 	<li><a href="/category.html?id=90">Central Europe</a></li>
195 | 	<li><a href="/category.html?id=29">Chinese</a></li>
196 | 	<li><a href="/category.html?id=88">Cyrillic</a></li>
197 | 	<li><a href="/category.html?id=91">Ethiopic</a></li>
198 | 	<li><a href="/category.html?id=99">Georgian</a></li>
199 | 	<li><a href="/category.html?id=33">Greek</a></li></ul>
200 | 
201 | <ul >
202 | <li><a href="/category.html?id=85">Hebrew</a></li>
203 | 	<li><a href="/category.html?id=76">Japanese</a></li>
204 | 	<li><a href="/category.html?id=95">Korean</a></li>
205 | 	<li><a href="/category.html?id=98">Lao</a></li>
206 | 	<li><a href="/category.html?id=31">Mexican</a></li>
207 | 	<li><a href="/category.html?id=94">Mongolian</a></li>
208 | 	<li><a href="/category.html?id=32">Roman</a></li>
209 | 	<li><a href="/category.html?id=34">Russian</a></li>
210 | 	<li><a href="/category.html?id=86">Thai</a></li>
211 | 	<li><a href="/category.html?id=87">Tibetan</a></li>
212 | 	<li><a href="/category.html?id=92">Unicode</a></li>
213 | 	<li><a href="/category.html?id=100">Various</a></li>
214 | 	<li><a href="/category.html?id=96">Vietnamese</a></li></ul>
215 | 
216 | <ul >
217 | <li class="bld"><a href="/category.html?id=6">Gothic</a></li>
218 | 	<li><a href="/category.html?id=45">Celtic</a></li>
219 | 	<li><a href="/category.html?id=46">Initials</a></li>
220 | 	<li><a href="/category.html?id=43">Medieval</a></li>
221 | 	<li><a href="/category.html?id=44">Modern</a></li>
222 | 	<li><a href="/category.html?id=72">Various</a></li>
223 | 	<li class="active">&nbsp;</li>
224 | 	<li class="bld"><a href="/category.html?id=12">Holiday</a></li>
225 | 	<li><a href="/category.html?id=50">Christmas</a></li>
226 | 	<li><a href="/category.html?id=66">Decorative</a></li>
227 | 	<li><a href="/category.html?id=48">Easter</a></li>
228 | 	<li><a href="/category.html?id=49">Halloween</a></li>
229 | 	<li><a href="/category.html?id=47">Valentine</a></li></ul>
230 | 
231 | <ul class="nodots">
232 | <li class="bld"><a href="/category.html?id=13">Script</a></li>
233 | 	<li><a href="/category.html?id=54">Brush</a></li>
234 | 	<li><a href="/category.html?id=51">Calligraphy</a></li>
235 | 	<li><a href="/category.html?id=56">Graffiti</a></li>
236 | 	<li><a href="/category.html?id=53">Handwritten</a></li>
237 | 	<li><a href="/category.html?id=52">School</a></li>
238 | 	<li><a href="/category.html?id=55">Trash</a></li></ul>
239 | </div>
240 | 			</div>
241 | 			<div class="cl"></div>
242 | </div>
243 | <!-- Navigation end -->
244 | 
245 | <!-- Main start -->
246 | <div id="chold">
247 | 
248 | 		    <div id="content">
249 | 				<!-- Content start -->
250 | 				<div id="container">
251 |     <div class="title">
252 | 		<span id="h1"><h1>Font download</h1></span>
253 | 			<span class="socialcontent">
254 | 				Follow us:
255 | 					<a href="/feed.html" title="RSS feed"><img src="data:image/gif;base64,R0lGODlhJAASAMQAAPmrb/////3kz/iNLfibUPV9IvvDlfq5g/aBJfJtFv7z6vFoEvzWufmUPPNwGPeFKfaNPfvJovzdxPmjW/R3Hf7t4fV6H/zRrfJrFPR0G//7+PFnEfNzGviJKv/69v/+/CH5BAAAAAAALAAAAAAkABIAAAX/4CaOS4lhScJUWuC+imQQSGHf90guZ5pUr6BQcIAUajWbblPioRIOg3D6qhweiGxtaXpCAQFPRUIWKKgBwUSL4DpTDoeFAEFQLBYEZHIQfIQeV1k6TT1QDhkZFHcWN1kPExctQQYPD4RvhxyJjI6PlhMCQpWYhnGbBQAGDKwRBxOWlh0DUpQ7macZD2dCHxUGDR2zHQd/Lh+3Xg6bihJoHwoHswMDxS/JcMuKGQdoAX8MDdS01yJd2ZuLEK4ABxECHkIS4tQXLjum2ot4R1kdBBeMuQhHrQEQfE9y7fMkawKQFwbGdUOITlGnfrL+iToGoGAFipos8kMA4AIwYf88JhiTMM4AtpD7GkWAQUBYtRceJgzoMOElFGaMIExyUUmYQWMRhYUAADs=" width="36" height="18" alt="RSS feed" /></a><a href="http://www.twitter.com/fonts2u" target="_blank" title="Follow us at Twitter!" class="twitter"><img src="data:image/gif;base64,R0lGODlhJAASAMQAAOr7/3ri/i7R/F3c/THS/DXS/Gjf/mXe/sj0/kvY/Zfp/mzg/rzx/kDV/fT8/1DZ/afs/obl/mHe/UXX/VXb/dT2/j3V/Vnb/TvU/bPv/vn+//z+/974/9r3/////zjT/CH5BAAAAAAALAAAAAAkABIAAAX/oCCOImEWV+VwUdNMcCInT23fJHlOledzFNhk9rjUKEjkg/LIlU4Xh8+jCcQSAQWkkgkkvxSn4FR4AKYexSTCQDg2U4DhQq+HcyZC4TNhoB0AcGhTEQOGhxdOZB8YAYOPaIUDEocDinp7GAOQkAgGEqChlnh6H4wPHZwaDh0KAQegB7CwEqSlGBYWEIMAFQwBh7Gyw7CkBZkWDRFoGxFIF4bCBtPTssbIDRJnPhsKFNDRstQL1AfXjMkTCGgM39ESBwYL8/TT57gvfnEB4AcREAw6/Kpn4F66AFLiZICQQYUgDwjokTPoog+nRwAIUoQR5SIaDhp1YEJXcUKAbRcBEyggV43iiyELejBbASHCq3IHQgAAOw==" width="36" height="18" alt="Twitter" /></a><a href="http://www.facebook.com/fonts2u" target="_blank" title="Follow us on Facebook!"><img src="data:image/gif;base64,R0lGODlhJAASAMQAAE50ws7Y60xxvv///1B2xUhrtEFhpGyHwJOn0TxamT5dnbfE30Nlqqq73Vt6uYWcy0puuEdpsfL0+d7k8j9en0VnrlRysDtZmPz9/u/x9ztZlz1cmz9goff5/Ojs9UdnqSH5BAAAAAAALAAAAAAkABIAAAX9oCaO4pUk26ZQLJIN8BBUdGTfN0meqLJyj5iwgisYjwVd6aT6GSTCQScAiSCvSSWvSeFYoo2DFQkpmyFKE0rFMnyHxON5rmX6um4oDHMwzgUQAoKAdSk/HAYfATEYCxYIAQdlg5QCOmqGeAYGCEIYAxgYDZWVl3aHHwcLUXsBlACwsJYkmHeIC5+sMBOCsb4AOluHHAe6MAEPAAKxBM2wwXaaDLoSgb2wzdnAO2tOmx4ZuEIOg9jZ2dCZiJsfFRYTQgjlAOfo3OqbBgwMFasxrtfqNYPWQ5M+fg9ySZlH79y2EcK6rNtXwUEHIQcYanu4pIc3ihAWxRh17ReAEAA7" width="36" height="18" alt="Facebook" /></a>
256 | 	</span>
257 | 		<div class="clr"></div>
258 |    </div>
259 | 	
260 |   <form name="entryform" action="/download.htm" method="post" id="dlform">
261 |   
262 |     <input type="hidden" name="id" value="19271" />
263 |     <input type="hidden" name="family" value="FreeMono" />
264 |     <input type="hidden" name="total" value="4" />
265 |     
266 |     <p><strong>Select below your desired version of this font:</strong></p>
267 |     <br />
268 |     
269 |     <table id="download">
270 |       		<tr onclick="checker(this);">
271 | 
272 | 	<td class="switch">
273 | 		<input type="checkbox" name="fhash[e39d520c75e7440850e07a46a24b8925.ttf]" value="FreeMono.ttf" checked="checked" />
274 | 	</td>
275 | 	
276 | 	<td class="name blued">
277 | 		Free Monospaced	</td>
278 | 	
279 | 	<td class="file">
280 | 		FreeMono.ttf	</td>
281 | 
282 | 	<td class="type">
283 | 		TrueType	</td>
284 | 	
285 | 	<td class="platform">
286 | 		Unicode / Macintosh / Microsoft	</td>
287 | 
288 | </tr>
289 | <tr onclick="checker(this);">
290 | 
291 | 	<td class="switch">
292 | 		<input type="checkbox" name="fhash[fb0a6033272d88e66a84baea5c1b7353.ttf]" value="FreeMonoBold.ttf"  />
293 | 	</td>
294 | 	
295 | 	<td class="name">
296 | 		Free Monospaced Bold	</td>
297 | 	
298 | 	<td class="file">
299 | 		FreeMonoBold.ttf	</td>
300 | 
301 | 	<td class="type">
302 | 		TrueType	</td>
303 | 	
304 | 	<td class="platform">
305 | 		Unicode / Macintosh / Microsoft	</td>
306 | 
307 | </tr>
308 | <tr onclick="checker(this);">
309 | 
310 | 	<td class="switch">
311 | 		<input type="checkbox" name="fhash[0723d2a88966a433edeb215604f3ff14.ttf]" value="FreeMonoBoldOblique.ttf"  />
312 | 	</td>
313 | 	
314 | 	<td class="name">
315 | 		Free Monospaced Bold Oblique	</td>
316 | 	
317 | 	<td class="file">
318 | 		FreeMonoBoldOblique.ttf	</td>
319 | 
320 | 	<td class="type">
321 | 		TrueType	</td>
322 | 	
323 | 	<td class="platform">
324 | 		Unicode / Macintosh / Microsoft	</td>
325 | 
326 | </tr>
327 | <tr onclick="checker(this);">
328 | 
329 | 	<td class="switch">
330 | 		<input type="checkbox" name="fhash[d11355f807979a0dc10ef3624b81fc6c.ttf]" value="FreeMonoOblique.ttf"  />
331 | 	</td>
332 | 	
333 | 	<td class="name">
334 | 		Free Monospaced Oblique	</td>
335 | 	
336 | 	<td class="file">
337 | 		FreeMonoOblique.ttf	</td>
338 | 
339 | 	<td class="type">
340 | 		TrueType	</td>
341 | 	
342 | 	<td class="platform">
343 | 		Unicode / Macintosh / Microsoft	</td>
344 | 
345 | </tr>
346 |     </table>
347 |     <br />
348 |     <p>The data will be supplied in a Zip archive. This will be a single .zip file containing selected font file(s).</p>
349 |     
350 |     <br /><br />
351 |     <p><strong>To start downloading please confirm your request.</strong></p>
352 |     
353 |     	
354 | 		<input type="hidden" name="frm[hash]" value="370decf4b11292c46829041db6953c91" />	
355 | 		Enter the code shown below:
356 | 		
357 |    <div id="downcheck">
358 |    		<div><img src="/captcha.html?hash=370decf4b11292c46829041db6953c91" alt="Antibot Code" width="250" height="90" /></div>
359 | 		<div class="enter"><input name="frm[code]" type="text" value="" autocomplete="off" /></div>
360 | 		<div class="code"><a href="/download.html?id=19271"><strong>Can't read the code?</strong></a></div>
361 | 		<div class="button"><input name="submit" type="submit" value="Confirm" class="sbtn" /></div>
362 |    </div>
363 |    
364 |   </form>
365 | </div>
366 | 				<!-- Content End -->
367 | 
368 | 				<!-- Banner start -->
369 | 				<div id="banner_bottom"></div>
370 | 				<!-- Banner End -->
371 | 
372 | 				<div class="clr"></div>
373 | 
374 | 				<!-- Footer start -->
375 | 				<div id="footer">
376 | 					<p>
377 | 						<small>
378 | 							Fonts available at <a href="/">Fonts2u.com</a> are either GNU/GPL, Freeware, free for Personal use, Donationware,  Shareware or Demo. Although we have indicated the license type, please make sure to double check it by reading the information shown in the details area of each font to avoid any confusion. 
379 | 						</small>
380 | 					</p>
381 | 
382 | 					<div class="line"></div>
383 | 					<div class="rght">
384 | 						<a href="/feed.html">RSS feed</a> |
385 | 						<a href="http://www.twitter.com/fonts2u" target="_blank">Follow us at Twitter</a> |
386 | 						<a href="http://www.facebook.com/fonts2u" target="_blank">Follow us on Facebook</a> |
387 | 						<a href="/references.html">References</a> |						<a href="/faq.html">Faq</a> |
388 | 						<a href="/privacy.html">Privacy policy</a> |
389 | 						<a href="/contact.html">Contact</a>
390 | 						
391 | 						<p>
392 | 							Copyright &copy; 2015 Yuxar Consulting Corp., all rights reserved.
393 | 						</p>
394 | 					</div>
395 | 
396 | 				</div>
397 | 				<!-- Footer end -->
398 | 			</div>
399 | </div>			
400 | 			
401 | <!-- Main end -->
402 | 
403 | </div>
404 | 
405 |             <script src="http://gzip.fonts2u.com/js/3-4-2014.min.js" language="JavaScript" type="text/javascript"></script>
406 | </body>
407 | 
408 | </html>
409 | 


--------------------------------------------------------------------------------
/docs/images/bar.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yaronn/blessed-contrib/ecd48d98c4c63a9cacfe20f68f568b3321ec46f5/docs/images/bar.gif


--------------------------------------------------------------------------------
/docs/images/dashboard.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yaronn/blessed-contrib/ecd48d98c4c63a9cacfe20f68f568b3321ec46f5/docs/images/dashboard.png


--------------------------------------------------------------------------------
/docs/images/donut.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yaronn/blessed-contrib/ecd48d98c4c63a9cacfe20f68f568b3321ec46f5/docs/images/donut.gif


--------------------------------------------------------------------------------
/docs/images/gauge.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yaronn/blessed-contrib/ecd48d98c4c63a9cacfe20f68f568b3321ec46f5/docs/images/gauge.gif


--------------------------------------------------------------------------------
/docs/images/lcd.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yaronn/blessed-contrib/ecd48d98c4c63a9cacfe20f68f568b3321ec46f5/docs/images/lcd.gif


--------------------------------------------------------------------------------
/docs/images/line.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yaronn/blessed-contrib/ecd48d98c4c63a9cacfe20f68f568b3321ec46f5/docs/images/line.gif


--------------------------------------------------------------------------------
/docs/images/log.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yaronn/blessed-contrib/ecd48d98c4c63a9cacfe20f68f568b3321ec46f5/docs/images/log.gif


--------------------------------------------------------------------------------
/docs/images/map.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yaronn/blessed-contrib/ecd48d98c4c63a9cacfe20f68f568b3321ec46f5/docs/images/map.gif


--------------------------------------------------------------------------------
/docs/images/markdown.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yaronn/blessed-contrib/ecd48d98c4c63a9cacfe20f68f568b3321ec46f5/docs/images/markdown.png


--------------------------------------------------------------------------------
/docs/images/picture.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yaronn/blessed-contrib/ecd48d98c4c63a9cacfe20f68f568b3321ec46f5/docs/images/picture.png


--------------------------------------------------------------------------------
/docs/images/spark.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yaronn/blessed-contrib/ecd48d98c4c63a9cacfe20f68f568b3321ec46f5/docs/images/spark.gif


--------------------------------------------------------------------------------
/docs/images/stacked-bar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yaronn/blessed-contrib/ecd48d98c4c63a9cacfe20f68f568b3321ec46f5/docs/images/stacked-bar.png


--------------------------------------------------------------------------------
/docs/images/stackgauge.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yaronn/blessed-contrib/ecd48d98c4c63a9cacfe20f68f568b3321ec46f5/docs/images/stackgauge.gif


--------------------------------------------------------------------------------
/docs/images/table.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yaronn/blessed-contrib/ecd48d98c4c63a9cacfe20f68f568b3321ec46f5/docs/images/table.gif


--------------------------------------------------------------------------------
/docs/images/term3.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yaronn/blessed-contrib/ecd48d98c4c63a9cacfe20f68f568b3321ec46f5/docs/images/term3.gif


--------------------------------------------------------------------------------
/docs/images/tree.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yaronn/blessed-contrib/ecd48d98c4c63a9cacfe20f68f568b3321ec46f5/docs/images/tree.gif


--------------------------------------------------------------------------------
/docs/images/truload.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yaronn/blessed-contrib/ecd48d98c4c63a9cacfe20f68f568b3321ec46f5/docs/images/truload.png


--------------------------------------------------------------------------------
/examples/bar.js:
--------------------------------------------------------------------------------
 1 | var blessed = require('blessed')
 2 |   , contrib = require('../')
 3 |   , screen = blessed.screen()
 4 |   , bar = contrib.bar(
 5 |        { label: 'Server Utilization (%)'
 6 |        , barWidth: 4
 7 |        , barSpacing: 6
 8 |        , xOffset: 0
 9 |        , maxHeight: 9
10 |        , height: "40%"})
11 | 
12 | screen.append(bar)
13 | 
14 | bar.setData(
15 |        { titles: ['bar1', 'bar2']
16 |        , data: [5, 10]})
17 | 
18 | screen.render()


--------------------------------------------------------------------------------
/examples/carousel.js:
--------------------------------------------------------------------------------
 1 | var blessed = require('blessed')
 2 |   , contrib = require('../')
 3 |   , screen = blessed.screen()
 4 | 
 5 | function page1(screen) {  
 6 |    var grid = new contrib.grid({rows: 4, cols: 4, screen: screen})
 7 | 
 8 |    var line = grid.set(1, 0, 2, 2, contrib.line, 
 9 |      { style: 
10 |        { line: "yellow"
11 |        , text: "green"
12 |        , baseline: "black"}
13 |      , xLabelPadding: 3
14 |      , xPadding: 5
15 |      , label: 'Stocks'})
16 | 
17 |    var map = grid.set(1, 2, 2, 2, contrib.map, {label: 'Servers Location'})
18 | 
19 |    var box = blessed.box({content: 'click right-left arrows or wait 3 seconds for the next layout in the carousel', top: '80%', left: '10%'})
20 |    screen.append(box)
21 | 
22 |    var lineData = {
23 |       x: ['t1', 't2', 't3', 't4'],
24 |       y: [5, 1, 7, 5]
25 |    }
26 | 
27 |    line.setData([lineData]) 
28 | }
29 | 
30 | function page2(screen) {  
31 |   var line = contrib.line(
32 |    { width: 80
33 |    , height: 30
34 |    , left: 15
35 |    , top: 12  
36 |    , xPadding: 5
37 |    , label: 'Title'
38 |    })
39 | 
40 |   var data = [ { title: 'us-east',
41 |              x: ['t1', 't2', 't3', 't4'],
42 |              y: [0, 0.0695652173913043, 0.11304347826087, 2],
43 |              style: {
44 |               line: 'red'
45 |              }
46 |            }
47 |         ]
48 | 
49 |   screen.append(line)
50 |   line.setData(data)
51 | 
52 |   var box = blessed.box({content: 'click right-left arrows or wait 3 seconds for the next layout in the carousel', top: '80%', left: '10%'})
53 |   screen.append(box)
54 | 
55 | }
56 | 
57 | screen.key(['escape', 'q', 'C-c'], function(ch, key) {
58 |   return process.exit(0);
59 | });
60 | 
61 | var carousel = new contrib.carousel( [page1, page2]
62 |                                    , { screen: screen
63 |                                      , interval: 3000
64 |                                      , controlKeys: true })
65 | carousel.start()
66 | 


--------------------------------------------------------------------------------
/examples/dashboard-random-colors.js:
--------------------------------------------------------------------------------
  1 | var blessed = require('blessed')
  2 |   , contrib = require('../index')
  3 | 
  4 | var screen = blessed.screen()
  5 | 
  6 | //create layout and widgets
  7 | 
  8 |   // Create a random color
  9 |   function randomColor() {
 10 |     return [Math.random() * 255,Math.random()*255, Math.random()*255]
 11 | }
 12 | 
 13 | var grid = new contrib.grid({rows: 12, cols: 12, screen: screen})
 14 | 
 15 | /**
 16 |  * Donut Options
 17 |   self.options.radius = options.radius || 14; // how wide is it? over 5 is best
 18 |   self.options.arcWidth = options.arcWidth || 4; //width of the donut
 19 |   self.options.yPadding = options.yPadding || 2; //padding from the top
 20 |  */
 21 | var donut = grid.set(8, 8, 4, 2, contrib.donut, 
 22 |   {
 23 |   label: 'Percent Donut',
 24 |   radius: 16,
 25 |   arcWidth: 4,
 26 |   yPadding: 2,
 27 |   data: [{label: 'Storage', percent: 87}]
 28 | })
 29 | 
 30 | // var latencyLine = grid.set(8, 8, 4, 2, contrib.line, 
 31 | //   { style: 
 32 | //     { line: "yellow"
 33 | //     , text: "green"
 34 | //     , baseline: "black"}
 35 | //   , xLabelPadding: 3
 36 | //   , xPadding: 5
 37 | //   , label: 'Network Latency (sec)'})
 38 | 
 39 | var gauge = grid.set(8, 10, 2, 2, contrib.gauge, {label: 'Storage', percent: [80,20]})
 40 | var gauge_two = grid.set(2, 9, 2, 3, contrib.gauge, {label: 'Deployment Progress', percent: 80})
 41 | 
 42 | var sparkline = grid.set(10, 10, 2, 2, contrib.sparkline, 
 43 |   { label: 'Throughput (bits/sec)'
 44 |   , tags: true
 45 |   , style: { fg: 'blue', titleFg: 'white' }})
 46 | 
 47 | var bar = grid.set(4, 6, 4, 3, contrib.bar, 
 48 |   { label: 'Server Utilization (%)'
 49 |   , barWidth: 4
 50 |   , barSpacing: 6
 51 |   , xOffset: 2
 52 |   , maxHeight: 9})
 53 | 
 54 | var table =  grid.set(4, 9, 4, 3, contrib.table, 
 55 |   { keys: true
 56 |   , fg: 'green'
 57 |   , label: 'Active Processes'
 58 |   , columnSpacing: 1
 59 |   , columnWidth: [24, 10, 10]})
 60 | 
 61 | /*
 62 |  *
 63 |  * LCD Options
 64 | //these options need to be modified epending on the resulting positioning/size
 65 |   options.segmentWidth = options.segmentWidth || 0.06; // how wide are the segments in % so 50% = 0.5
 66 |   options.segmentInterval = options.segmentInterval || 0.11; // spacing between the segments in % so 50% = 0.5
 67 |   options.strokeWidth = options.strokeWidth || 0.11; // spacing between the segments in % so 50% = 0.5
 68 | //default display settings
 69 |   options.elements = options.elements || 3; // how many elements in the display. or how many characters can be displayed.
 70 |   options.display = options.display || 321; // what should be displayed before anything is set
 71 |   options.elementSpacing = options.spacing || 4; // spacing between each element
 72 |   options.elementPadding = options.padding || 2; // how far away from the edges to put the elements
 73 | //coloring
 74 |   options.color = options.color || "white";
 75 | */
 76 | var lcdLineOne = grid.set(0,9,2,3, contrib.lcd,
 77 |   {
 78 |     label: "LCD Test",
 79 |     segmentWidth: 0.06,
 80 |     segmentInterval: 0.11,
 81 |     strokeWidth: 0.1,
 82 |     elements: 5,
 83 |     display: 3210,
 84 |     elementSpacing: 4,
 85 |     elementPadding: 2
 86 |   }
 87 | );
 88 | 
 89 | var errorsLine = grid.set(0, 6, 4, 3, contrib.line, 
 90 |   { style: 
 91 |     { line: randomColor()
 92 |     , text: randomColor()
 93 |     , baseline: randomColor()}
 94 |   , label: 'Errors Rate'
 95 |   , maxY: 60
 96 |   , showLegend: true })
 97 | 
 98 | var transactionsLine = grid.set(0, 0, 6, 6, contrib.line, 
 99 |           { showNthLabel: 5
100 |           , maxY: 100
101 |           , label: 'Total Transactions'
102 |           , showLegend: true
103 |           , legend: {width: 10}})
104 | 
105 | var map = grid.set(6, 0, 6, 6, contrib.map, {label: 'Servers Location'})
106 | 
107 | var log = grid.set(8, 6, 4, 2, contrib.log, 
108 |   { fg: randomColor()
109 |   , selectedFg: randomColor()
110 |   , label: 'Server Log'})
111 | 
112 | 
113 | //dummy data
114 | var servers = ['US1', 'US2', 'EU1', 'AU1', 'AS1', 'JP1']
115 | var commands = ['grep', 'node', 'java', 'timer', '~/ls -l', 'netns', 'watchdog', 'gulp', 'tar -xvf', 'awk', 'npm install']
116 | 
117 | 
118 | //set dummy data on gauge
119 | var gauge_percent = 0
120 | setInterval(function() {
121 |   gauge.setData([gauge_percent, 100-gauge_percent]);
122 |   gauge_percent++;
123 |   if (gauge_percent>=100) gauge_percent = 0  
124 | }, 200)
125 | 
126 | var gauge_percent_two = 0
127 | setInterval(function() {
128 |   gauge_two.setData(gauge_percent_two);
129 |   gauge_percent_two++;
130 |   if (gauge_percent_two>=100) gauge_percent_two = 0  
131 | }, 200);
132 | 
133 | 
134 | //set dummy data on bar chart
135 | function fillBar() {
136 |   var arr = []
137 |   for (var i=0; i<servers.length; i++) {
138 |     arr.push(Math.round(Math.random()*10))
139 |   }
140 |   bar.setData({titles: servers, data: arr})
141 | }
142 | fillBar()
143 | setInterval(fillBar, 2000)
144 | 
145 | 
146 | //set dummy data for table
147 | function generateTable() {
148 |    var data = []
149 | 
150 |    for (var i=0; i<30; i++) {
151 |      var row = []          
152 |      row.push(commands[Math.round(Math.random()*(commands.length-1))])
153 |      row.push(Math.round(Math.random()*5))
154 |      row.push(Math.round(Math.random()*100))
155 | 
156 |      data.push(row)
157 |    }
158 | 
159 |    table.setData({headers: ['Process', 'Cpu (%)', 'Memory'], data: data})
160 | }
161 | 
162 | generateTable()
163 | table.focus()
164 | setInterval(generateTable, 3000)
165 | 
166 | 
167 | //set log dummy data
168 | setInterval(function() {
169 |    var rnd = Math.round(Math.random()*2)
170 |    if (rnd==0) log.log('starting process ' + commands[Math.round(Math.random()*(commands.length-1))])   
171 |    else if (rnd==1) log.log('terminating server ' + servers[Math.round(Math.random()*(servers.length-1))])
172 |    else if (rnd==2) log.log('avg. wait time ' + Math.random().toFixed(2))
173 |    screen.render()
174 | }, 500)
175 | 
176 | 
177 | //set spark dummy data
178 | var spark1 = [1,2,5,2,1,5,1,2,5,2,1,5,4,4,5,4,1,5,1,2,5,2,1,5,1,2,5,2,1,5,1,2,5,2,1,5]
179 | var spark2 = [4,4,5,4,1,5,1,2,5,2,1,5,4,4,5,4,1,5,1,2,5,2,1,5,1,2,5,2,1,5,1,2,5,2,1,5]
180 | 
181 | refreshSpark()
182 | setInterval(refreshSpark, 1000)
183 | 
184 | function refreshSpark() {
185 |   spark1.shift()
186 |   spark1.push(Math.random()*5+1)       
187 |   spark2.shift()
188 |   spark2.push(Math.random()*5+1)       
189 |   sparkline.setData(['Server1', 'Server2'], [spark1, spark2])  
190 | }
191 | 
192 | 
193 | 
194 | //set map dummy markers
195 | var marker = true
196 | setInterval(function() {
197 |    if (marker) {
198 |     map.addMarker({"lon" : "-79.0000", "lat" : "37.5000", color: randomColor(), char: 'X' })
199 |     map.addMarker({"lon" : "-122.6819", "lat" : "45.5200" })
200 |     map.addMarker({"lon" : "-6.2597", "lat" : "53.3478" })
201 |     map.addMarker({"lon" : "103.8000", "lat" : "1.3000" })
202 |    }
203 |    else {
204 |     map.clearMarkers()
205 |    }
206 |    marker =! marker
207 |    screen.render()
208 | }, 1000)
209 | 
210 | //set line charts dummy data
211 | 
212 | var transactionsData = {
213 |    title: 'USA',
214 |    style: {line:'red'},
215 |    x: ['00:00', '00:05', '00:10', '00:15', '00:20', '00:30', '00:40', '00:50', '01:00', '01:10', '01:20', '01:30', '01:40', '01:50', '02:00', '02:10', '02:20', '02:30', '02:40', '02:50', '03:00', '03:10', '03:20', '03:30', '03:40', '03:50', '04:00', '04:10', '04:20', '04:30'],
216 |    y: [0, 20, 40, 45, 45, 50, 55, 70, 65, 58, 50, 55, 60, 65, 70, 80, 70, 50, 40, 50, 60, 70, 82, 88, 89, 89, 89, 80, 72, 70]
217 | }
218 | 
219 | var transactionsData1 = {
220 |    title: 'Europe',
221 |    style: {line:'yellow'},
222 |    x: ['00:00', '00:05', '00:10', '00:15', '00:20', '00:30', '00:40', '00:50', '01:00', '01:10', '01:20', '01:30', '01:40', '01:50', '02:00', '02:10', '02:20', '02:30', '02:40', '02:50', '03:00', '03:10', '03:20', '03:30', '03:40', '03:50', '04:00', '04:10', '04:20', '04:30'],
223 |    y: [0, 5, 5, 10, 10, 15, 20, 30, 25, 30, 30, 20, 20, 30, 30, 20, 15, 15, 19, 25, 30, 25, 25, 20, 25, 30, 35, 35, 30, 30]
224 | }
225 | 
226 | var errorsData = {
227 |    title: 'server 1',
228 |    x: ['00:00', '00:05', '00:10', '00:15', '00:20', '00:25'],
229 |    y: [30, 50, 70, 40, 50, 20]
230 | }
231 | 
232 | var latencyData = {
233 |    x: ['t1', 't2', 't3', 't4'],
234 |    y: [5, 1, 7, 5]
235 | }
236 | 
237 | setLineData([transactionsData, transactionsData1], transactionsLine)
238 | setLineData([errorsData], errorsLine)
239 | // setLineData([latencyData], latencyLine)
240 | 
241 | setInterval(function() {
242 |    setLineData([transactionsData, transactionsData1], transactionsLine)
243 |    screen.render()
244 | }, 500)
245 | 
246 | setInterval(function() {   
247 |     setLineData([errorsData], errorsLine)
248 | }, 1500)
249 | 
250 | setInterval(function(){
251 |   var colors = [randomColor(),randomColor(),randomColor(),randomColor(),randomColor()];
252 |   var text = ['A','B','C','D','E','F','G','H','I','J','K','L'];
253 | 
254 |   var value = Math.round(Math.random() * 100);
255 |   lcdLineOne.setDisplay(value + text[value%12]);
256 |   lcdLineOne.setOptions({
257 |     color: colors[value%5],
258 |     elementPadding: 4
259 |   });
260 |   screen.render()
261 | }, 1500);
262 | 
263 | var pct = 0.00;
264 | 
265 | function updateDonut(){
266 |   if (pct > 0.99) pct = 0.00;
267 |   var color = "green";
268 |   if (pct >= 0.25) color = "cyan";
269 |   if (pct >= 0.5) color = "yellow";
270 |   if (pct >= 0.75) color = "red";  
271 |   donut.setData([
272 |     {percent: parseFloat((pct+0.00) % 1).toFixed(2), label: 'storage', 'color': color}
273 |   ]);
274 |   pct += 0.01;
275 | }
276 | 
277 | setInterval(function() {   
278 |    updateDonut();
279 |    screen.render()
280 | }, 500)
281 | 
282 | function setLineData(mockData, line) {
283 |   for (var i=0; i<mockData.length; i++) {
284 |     var last = mockData[i].y[mockData[i].y.length-1]
285 |     mockData[i].y.shift()
286 |     var num = Math.max(last + Math.round(Math.random()*10) - 5, 10)    
287 |     mockData[i].y.push(num)  
288 |   }
289 |   
290 |   line.setData(mockData)
291 | }
292 | 
293 | 
294 | screen.key(['escape', 'q', 'C-c'], function(ch, key) {
295 |   return process.exit(0);
296 | });
297 | 
298 | screen.render()
299 | 


--------------------------------------------------------------------------------
/examples/dashboard.js:
--------------------------------------------------------------------------------
  1 | var blessed = require('blessed')
  2 |   , contrib = require('../index')
  3 | 
  4 | var screen = blessed.screen()
  5 | 
  6 | //create layout and widgets
  7 | 
  8 | var grid = new contrib.grid({rows: 12, cols: 12, screen: screen})
  9 | 
 10 | /**
 11 |  * Donut Options
 12 |   self.options.radius = options.radius || 14; // how wide is it? over 5 is best
 13 |   self.options.arcWidth = options.arcWidth || 4; //width of the donut
 14 |   self.options.yPadding = options.yPadding || 2; //padding from the top
 15 |  */
 16 | var donut = grid.set(8, 8, 4, 2, contrib.donut, 
 17 |   {
 18 |   label: 'Percent Donut',
 19 |   radius: 16,
 20 |   arcWidth: 4,
 21 |   yPadding: 2,
 22 |   data: [{label: 'Storage', percent: 87}]
 23 | })
 24 | 
 25 | // var latencyLine = grid.set(8, 8, 4, 2, contrib.line, 
 26 | //   { style: 
 27 | //     { line: "yellow"
 28 | //     , text: "green"
 29 | //     , baseline: "black"}
 30 | //   , xLabelPadding: 3
 31 | //   , xPadding: 5
 32 | //   , label: 'Network Latency (sec)'})
 33 | 
 34 | var gauge = grid.set(8, 10, 2, 2, contrib.gauge, {label: 'Storage', percent: [80,20]})
 35 | var gauge_two = grid.set(2, 9, 2, 3, contrib.gauge, {label: 'Deployment Progress', percent: 80})
 36 | 
 37 | var sparkline = grid.set(10, 10, 2, 2, contrib.sparkline, 
 38 |   { label: 'Throughput (bits/sec)'
 39 |   , tags: true
 40 |   , style: { fg: 'blue', titleFg: 'white' }})
 41 | 
 42 | var bar = grid.set(4, 6, 4, 3, contrib.bar, 
 43 |   { label: 'Server Utilization (%)'
 44 |   , barWidth: 4
 45 |   , barSpacing: 6
 46 |   , xOffset: 2
 47 |   , maxHeight: 9})
 48 | 
 49 | var table =  grid.set(4, 9, 4, 3, contrib.table, 
 50 |   { keys: true
 51 |   , fg: 'green'
 52 |   , label: 'Active Processes'
 53 |   , columnSpacing: 1
 54 |   , columnWidth: [24, 10, 10]})
 55 | 
 56 | /*
 57 |  *
 58 |  * LCD Options
 59 | //these options need to be modified epending on the resulting positioning/size
 60 |   options.segmentWidth = options.segmentWidth || 0.06; // how wide are the segments in % so 50% = 0.5
 61 |   options.segmentInterval = options.segmentInterval || 0.11; // spacing between the segments in % so 50% = 0.5
 62 |   options.strokeWidth = options.strokeWidth || 0.11; // spacing between the segments in % so 50% = 0.5
 63 | //default display settings
 64 |   options.elements = options.elements || 3; // how many elements in the display. or how many characters can be displayed.
 65 |   options.display = options.display || 321; // what should be displayed before anything is set
 66 |   options.elementSpacing = options.spacing || 4; // spacing between each element
 67 |   options.elementPadding = options.padding || 2; // how far away from the edges to put the elements
 68 | //coloring
 69 |   options.color = options.color || "white";
 70 | */
 71 | var lcdLineOne = grid.set(0,9,2,3, contrib.lcd,
 72 |   {
 73 |     label: "LCD Test",
 74 |     segmentWidth: 0.06,
 75 |     segmentInterval: 0.11,
 76 |     strokeWidth: 0.1,
 77 |     elements: 5,
 78 |     display: 3210,
 79 |     elementSpacing: 4,
 80 |     elementPadding: 2
 81 |   }
 82 | );
 83 | 
 84 | var errorsLine = grid.set(0, 6, 4, 3, contrib.line, 
 85 |   { style: 
 86 |     { line: "red"
 87 |     , text: "white"
 88 |     , baseline: "black"}
 89 |   , label: 'Errors Rate'
 90 |   , maxY: 60
 91 |   , showLegend: true })
 92 | 
 93 | var transactionsLine = grid.set(0, 0, 6, 6, contrib.line, 
 94 |           { showNthLabel: 5
 95 |           , maxY: 100
 96 |           , label: 'Total Transactions'
 97 |           , showLegend: true
 98 |           , legend: {width: 10}})
 99 | 
100 | var map = grid.set(6, 0, 6, 6, contrib.map, {label: 'Servers Location'})
101 | 
102 | var log = grid.set(8, 6, 4, 2, contrib.log, 
103 |   { fg: "green"
104 |   , selectedFg: "green"
105 |   , label: 'Server Log'})
106 | 
107 | 
108 | //dummy data
109 | var servers = ['US1', 'US2', 'EU1', 'AU1', 'AS1', 'JP1']
110 | var commands = ['grep', 'node', 'java', 'timer', '~/ls -l', 'netns', 'watchdog', 'gulp', 'tar -xvf', 'awk', 'npm install']
111 | 
112 | 
113 | //set dummy data on gauge
114 | var gauge_percent = 0
115 | setInterval(function() {
116 |   gauge.setData([gauge_percent, 100-gauge_percent]);
117 |   gauge_percent++;
118 |   if (gauge_percent>=100) gauge_percent = 0  
119 | }, 200)
120 | 
121 | var gauge_percent_two = 0
122 | setInterval(function() {
123 |   gauge_two.setData(gauge_percent_two);
124 |   gauge_percent_two++;
125 |   if (gauge_percent_two>=100) gauge_percent_two = 0  
126 | }, 200);
127 | 
128 | 
129 | //set dummy data on bar chart
130 | function fillBar() {
131 |   var arr = []
132 |   for (var i=0; i<servers.length; i++) {
133 |     arr.push(Math.round(Math.random()*10))
134 |   }
135 |   bar.setData({titles: servers, data: arr})
136 | }
137 | fillBar()
138 | setInterval(fillBar, 2000)
139 | 
140 | 
141 | //set dummy data for table
142 | function generateTable() {
143 |    var data = []
144 | 
145 |    for (var i=0; i<30; i++) {
146 |      var row = []          
147 |      row.push(commands[Math.round(Math.random()*(commands.length-1))])
148 |      row.push(Math.round(Math.random()*5))
149 |      row.push(Math.round(Math.random()*100))
150 | 
151 |      data.push(row)
152 |    }
153 | 
154 |    table.setData({headers: ['Process', 'Cpu (%)', 'Memory'], data: data})
155 | }
156 | 
157 | generateTable()
158 | table.focus()
159 | setInterval(generateTable, 3000)
160 | 
161 | 
162 | //set log dummy data
163 | setInterval(function() {
164 |    var rnd = Math.round(Math.random()*2)
165 |    if (rnd==0) log.log('starting process ' + commands[Math.round(Math.random()*(commands.length-1))])   
166 |    else if (rnd==1) log.log('terminating server ' + servers[Math.round(Math.random()*(servers.length-1))])
167 |    else if (rnd==2) log.log('avg. wait time ' + Math.random().toFixed(2))
168 |    screen.render()
169 | }, 500)
170 | 
171 | 
172 | //set spark dummy data
173 | var spark1 = [1,2,5,2,1,5,1,2,5,2,1,5,4,4,5,4,1,5,1,2,5,2,1,5,1,2,5,2,1,5,1,2,5,2,1,5]
174 | var spark2 = [4,4,5,4,1,5,1,2,5,2,1,5,4,4,5,4,1,5,1,2,5,2,1,5,1,2,5,2,1,5,1,2,5,2,1,5]
175 | 
176 | refreshSpark()
177 | setInterval(refreshSpark, 1000)
178 | 
179 | function refreshSpark() {
180 |   spark1.shift()
181 |   spark1.push(Math.random()*5+1)       
182 |   spark2.shift()
183 |   spark2.push(Math.random()*5+1)       
184 |   sparkline.setData(['Server1', 'Server2'], [spark1, spark2])  
185 | }
186 | 
187 | 
188 | 
189 | //set map dummy markers
190 | var marker = true
191 | setInterval(function() {
192 |    if (marker) {
193 |     map.addMarker({"lon" : "-79.0000", "lat" : "37.5000", color: 'yellow', char: 'X' })
194 |     map.addMarker({"lon" : "-122.6819", "lat" : "45.5200" })
195 |     map.addMarker({"lon" : "-6.2597", "lat" : "53.3478" })
196 |     map.addMarker({"lon" : "103.8000", "lat" : "1.3000" })
197 |    }
198 |    else {
199 |     map.clearMarkers()
200 |    }
201 |    marker =! marker
202 |    screen.render()
203 | }, 1000)
204 | 
205 | //set line charts dummy data
206 | 
207 | var transactionsData = {
208 |    title: 'USA',
209 |    style: {line: 'red'},
210 |    x: ['00:00', '00:05', '00:10', '00:15', '00:20', '00:30', '00:40', '00:50', '01:00', '01:10', '01:20', '01:30', '01:40', '01:50', '02:00', '02:10', '02:20', '02:30', '02:40', '02:50', '03:00', '03:10', '03:20', '03:30', '03:40', '03:50', '04:00', '04:10', '04:20', '04:30'],
211 |    y: [0, 20, 40, 45, 45, 50, 55, 70, 65, 58, 50, 55, 60, 65, 70, 80, 70, 50, 40, 50, 60, 70, 82, 88, 89, 89, 89, 80, 72, 70]
212 | }
213 | 
214 | var transactionsData1 = {
215 |    title: 'Europe',
216 |    style: {line: 'yellow'},
217 |    x: ['00:00', '00:05', '00:10', '00:15', '00:20', '00:30', '00:40', '00:50', '01:00', '01:10', '01:20', '01:30', '01:40', '01:50', '02:00', '02:10', '02:20', '02:30', '02:40', '02:50', '03:00', '03:10', '03:20', '03:30', '03:40', '03:50', '04:00', '04:10', '04:20', '04:30'],
218 |    y: [0, 5, 5, 10, 10, 15, 20, 30, 25, 30, 30, 20, 20, 30, 30, 20, 15, 15, 19, 25, 30, 25, 25, 20, 25, 30, 35, 35, 30, 30]
219 | }
220 | 
221 | var errorsData = {
222 |    title: 'server 1',
223 |    x: ['00:00', '00:05', '00:10', '00:15', '00:20', '00:25'],
224 |    y: [30, 50, 70, 40, 50, 20]
225 | }
226 | 
227 | var latencyData = {
228 |    x: ['t1', 't2', 't3', 't4'],
229 |    y: [5, 1, 7, 5]
230 | }
231 | 
232 | setLineData([transactionsData, transactionsData1], transactionsLine)
233 | setLineData([errorsData], errorsLine)
234 | // setLineData([latencyData], latencyLine)
235 | 
236 | setInterval(function() {
237 |    setLineData([transactionsData, transactionsData1], transactionsLine)
238 |    screen.render()
239 | }, 500)
240 | 
241 | setInterval(function() {   
242 |     setLineData([errorsData], errorsLine)
243 | }, 1500)
244 | 
245 | setInterval(function(){
246 |   var colors = ['green','magenta','cyan','red','blue'];
247 |   var text = ['A','B','C','D','E','F','G','H','I','J','K','L'];
248 | 
249 |   var value = Math.round(Math.random() * 100);
250 |   lcdLineOne.setDisplay(value + text[value%12]);
251 |   lcdLineOne.setOptions({
252 |     color: colors[value%5],
253 |     elementPadding: 4
254 |   });
255 |   screen.render()
256 | }, 1500);
257 | 
258 | var pct = 0.00;
259 | 
260 | function updateDonut(){
261 |   if (pct > 0.99) pct = 0.00;
262 |   var color = "green";
263 |   if (pct >= 0.25) color = "cyan";
264 |   if (pct >= 0.5) color = "yellow";
265 |   if (pct >= 0.75) color = "red";  
266 |   donut.setData([
267 |     {percent: parseFloat((pct+0.00) % 1).toFixed(2), label: 'storage', 'color': color}
268 |   ]);
269 |   pct += 0.01;
270 | }
271 | 
272 | setInterval(function() {   
273 |    updateDonut();
274 |    screen.render()
275 | }, 500)
276 | 
277 | function setLineData(mockData, line) {
278 |   for (var i=0; i<mockData.length; i++) {
279 |     var last = mockData[i].y[mockData[i].y.length-1]
280 |     mockData[i].y.shift()
281 |     var num = Math.max(last + Math.round(Math.random()*10) - 5, 10)    
282 |     mockData[i].y.push(num)  
283 |   }
284 |   
285 |   line.setData(mockData)
286 | }
287 | 
288 | 
289 | screen.key(['escape', 'q', 'C-c'], function(ch, key) {
290 |   return process.exit(0);
291 | });
292 | 
293 | // fixes https://github.com/yaronn/blessed-contrib/issues/10
294 | screen.on('resize', function() {
295 |   donut.emit('attach');
296 |   gauge.emit('attach');
297 |   gauge_two.emit('attach');
298 |   sparkline.emit('attach');
299 |   bar.emit('attach');
300 |   table.emit('attach');
301 |   lcdLineOne.emit('attach');
302 |   errorsLine.emit('attach');
303 |   transactionsLine.emit('attach');
304 |   map.emit('attach');
305 |   log.emit('attach');
306 | });
307 | 
308 | screen.render()
309 | 


--------------------------------------------------------------------------------
/examples/donut.js:
--------------------------------------------------------------------------------
 1 | var blessed = require('blessed')
 2 |   , contrib = require('../index')
 3 |   , screen = blessed.screen();
 4 | 
 5 | /**
 6 |  * Donut Options
 7 |   self.options.stroke = options.stroke || "magenta"
 8 |   self.options.radius = options.radius || 14;
 9 |   self.options.arcWidth = options.arcWidth || 4;
10 |   self.options.spacing = options.spacing || 2;
11 |   self.options.yPadding = options.yPadding || 2;
12 |  */
13 | 
14 | var donut = contrib.donut({
15 |   	label: 'Test',
16 |   	radius: 8,
17 |   	arcWidth: 3,
18 |   	yPadding: 2,
19 |     data: [
20 |       {percent: 80, label: 'web1', color: 'green'}
21 |     ]
22 |   });
23 |     
24 | screen.append(donut)
25 | 
26 | setInterval(updateDonuts, 5);
27 | 
28 | var pct = 0.00;
29 | 
30 | function updateDonuts(){
31 | 	if (pct > 0.99) pct = 0.00;
32 | 	donut.update([
33 | 		{percent: parseFloat((pct+0.00) % 1).toFixed(2), label: 'rcp','color':[100,200,170]},
34 | 		{percent: parseFloat((pct+0.25) % 1).toFixed(2), label: 'rcp','color':[128,128,128]},
35 | 		{percent: parseFloat((pct+0.50) % 1).toFixed(2), label: 'rcp','color':[255,0,0]},
36 | 		{percentAltNumber: 42, percent: parseFloat((pct+0.75) % 1).toFixed(2), label: 'web1', 'color': [255,128,0]}
37 | 	]);
38 | 	screen.render();
39 | 	pct += 0.01;
40 | }
41 | 
42 | screen.key(['escape', 'q', 'C-c'], function(ch, key) {
43 | 	return process.exit(0);
44 | });
45 | 


--------------------------------------------------------------------------------
/examples/explorer.js:
--------------------------------------------------------------------------------
  1 | var blessed = require('blessed')
  2 |   , contrib = require('../index')
  3 |   , fs = require('fs')
  4 |   , path = require('path')
  5 | 
  6 | var screen = blessed.screen()
  7 | 
  8 | //create layout and widgets
  9 | var grid = new contrib.grid({rows: 1, cols: 2, screen: screen})
 10 | 
 11 | var tree =  grid.set(0, 0, 1, 1, contrib.tree, 
 12 |   { style: { text: "red" }
 13 |   , template: { lines: true }
 14 |   , label: 'Filesystem Tree'})
 15 | 
 16 | var table =  grid.set(0, 1, 1, 1, contrib.table, 
 17 |   { keys: true
 18 |   , fg: 'green'
 19 |   , label: 'Informations'
 20 |   , columnWidth: [24, 10, 10]})
 21 | 
 22 | //file explorer
 23 | var explorer = { name: '/'
 24 |   , extended: true
 25 |   // Custom function used to recursively determine the node path
 26 |   , getPath: function(self){
 27 |       // If we don't have any parent, we are at tree root, so return the base case
 28 |       if(! self.parent)
 29 |         return '';
 30 |       // Get the parent node path and add this node name
 31 |       return self.parent.getPath(self.parent)+'/'+self.name;
 32 |     }
 33 |   // Child generation function
 34 |   , children: function(self){
 35 |       var result = {};
 36 |       var selfPath = self.getPath(self);
 37 |       try {
 38 |         // List files in this directory
 39 |         var children = fs.readdirSync(selfPath+'/');
 40 | 
 41 |         // childrenContent is a property filled with self.children() result
 42 |         // on tree generation (tree.setData() call)
 43 |         if (!self.childrenContent) {
 44 |           for(var child in children){
 45 |             child = children[child];
 46 |             var completePath = selfPath+'/'+child;
 47 |             if( fs.lstatSync(completePath).isDirectory() ){
 48 |               // If it's a directory we generate the child with the children generation function
 49 |               result[child] = { name: child, getPath: self.getPath, extended: false, children: self.children };
 50 |             }else{
 51 |               // Otherwise children is not set (you can also set it to "{}" or "null" if you want)
 52 |               result[child] = { name: child, getPath: self.getPath, extended: false };
 53 |             }
 54 |           }
 55 |         }else{
 56 |           result = self.childrenContent;
 57 |         }
 58 |       } catch (e){}
 59 |       return result;
 60 |     }
 61 | }
 62 | 
 63 | //set tree
 64 | tree.setData(explorer);
 65 | 
 66 | // Handling select event. Every custom property that was added to node is 
 67 | // available like the "node.getPath" defined above
 68 | tree.on('select',function(node){
 69 |   var path = node.getPath(node);
 70 |   var data = [];
 71 | 
 72 |   // The filesystem root return an empty string as a base case
 73 |   if ( path == '')
 74 |     path = '/';
 75 |   
 76 |   // Add data to right array
 77 |   data.push([path]);
 78 |   data.push(['']);
 79 |   try {
 80 |     // Add results
 81 |     data = data.concat(JSON.stringify(fs.lstatSync(path),null,2).split("\n").map(function(e){return [e]}));
 82 |     table.setData({headers: ['Info'], data: data});
 83 |   }catch(e){
 84 |     table.setData({headers: ['Info'], data: [[e.toString()]]});
 85 |   }
 86 |   
 87 |   screen.render();
 88 | });
 89 | 
 90 | //set default table
 91 | table.setData({headers: ['Info'], data: [[]]})
 92 | 
 93 | screen.key(['escape', 'q', 'C-c'], function(ch, key) {
 94 |   return process.exit(0);
 95 | });
 96 | 
 97 | screen.key(['tab'], function(ch, key) {
 98 |   if(screen.focused == tree.rows)
 99 |     table.focus();
100 |   else
101 |     tree.focus();
102 | });
103 | 
104 | tree.focus()
105 | screen.render()
106 | 


--------------------------------------------------------------------------------
/examples/gauge-list.js:
--------------------------------------------------------------------------------
 1 | var blessed = require('blessed')
 2 |   , contrib = require('../')
 3 |   , screen = blessed.screen()
 4 |   , grid = new contrib.grid({rows: 2, cols: 2, hideBorder: true, screen: screen})
 5 |   , gaugeList = grid.set(0, 0, 1, 2, contrib.gaugeList,
 6 |       {
 7 |         gaugeSpacing: 0,
 8 |         gaugeHeight: 1,
 9 |         gauges:
10 |           [ {showLabel: false, stack: [{percent: 30, stroke: 'green'}, {percent: 30, stroke: 'magenta'}, {percent: 40, stroke: 'cyan'}] }
11 |           , {showLabel: false, stack: [{percent: 40, stroke: 'yellow'}, {percent: 20, stroke: 'magenta'}, {percent: 40, stroke: 'green'}] }
12 |           , {showLabel: false, stack: [{percent: 50, stroke: 'red'}, {percent: 10, stroke: 'magenta'}, {percent: 40, stroke: 'cyan'}] } ]
13 |       }
14 |     )
15 | 
16 | screen.render()
17 | 
18 | 
19 | 
20 | screen.key(['escape', 'q', 'C-c'], function(ch, key) {
21 |   return process.exit(0);
22 | });
23 | 
24 | 


--------------------------------------------------------------------------------
/examples/gauge-stack.js:
--------------------------------------------------------------------------------
1 | var blessed = require('blessed')
2 |   , contrib = require('../')
3 |   , screen = blessed.screen()
4 |   , grid = new contrib.grid({rows: 2, cols: 2, hideBorder: true, screen: screen})
5 |   , gauge1 = grid.set(0, 0, 1, 1, contrib.gauge, {showLabel: false, stack: [{percent: 30, stroke: 'green'}, {percent: 30, stroke: 'magenta'}, {percent: 40, stroke: 'cyan'}] })
6 | 
7 | screen.render()
8 | 


--------------------------------------------------------------------------------
/examples/gauge.js:
--------------------------------------------------------------------------------
 1 | var blessed = require('blessed')
 2 |   , contrib = require('../')
 3 |   , screen = blessed.screen()
 4 |   , gauge = contrib.gauge({label: 'Progress'})
 5 |     
 6 | screen.append(gauge)
 7 | 
 8 | gauge.setPercent(25)
 9 | 
10 | screen.render()


--------------------------------------------------------------------------------
/examples/grid-no-border.js:
--------------------------------------------------------------------------------
 1 | 
 2 | var blessed = require('blessed')
 3 |   , contrib = require('../')
 4 |   , screen = blessed.screen()
 5 |   , grid = new contrib.grid({rows: 12, cols: 12, hideBorder: true, screen: screen})
 6 |   , map = grid.set(0, 0, 4, 4, contrib.map, {})
 7 |   , box = grid.set(4, 4, 4, 4, blessed.box, {content: 'My Box'})
 8 | 
 9 | screen.render()
10 | 


--------------------------------------------------------------------------------
/examples/grid.js:
--------------------------------------------------------------------------------
 1 | 
 2 | var blessed = require('blessed')
 3 |   , contrib = require('../')
 4 |   , screen = blessed.screen()
 5 |   , grid = new contrib.grid({rows: 12, cols: 12, screen: screen})
 6 |   , map = grid.set(0, 0, 4, 4, contrib.map, {label: 'World Map'})
 7 |   , box = grid.set(4, 4, 4, 4, blessed.box, {content: 'My Box'})
 8 | 
 9 | screen.render()
10 | 


--------------------------------------------------------------------------------
/examples/inline-data/bar.js:
--------------------------------------------------------------------------------
 1 | var blessed = require('blessed')
 2 |   , contrib = require('../../')
 3 |   , screen = blessed.screen()
 4 |   , bar = contrib.bar(
 5 |        { label: 'Server Utilization (%)'
 6 |        , barWidth: 4
 7 |        , barSpacing: 6
 8 |        , xOffset: 0
 9 |        , maxHeight: 9
10 |        , height: "40%"
11 |        , data: { titles: ['bar1', 'bar2']
12 |                , data: [5, 10]}
13 |                })
14 | 
15 | screen.append(bar)
16 | 
17 | screen.render()


--------------------------------------------------------------------------------
/examples/inline-data/donut.js:
--------------------------------------------------------------------------------
 1 | var blessed = require('blessed')
 2 |   , contrib = require('../../')
 3 |   , screen = blessed.screen()
 4 |   , donut = contrib.donut(
 5 |        {
 6 |         data: [ { color: 'red', percent: '50', label: 'a'}
 7 |               , { color: 'blue', percent: '20', label: 'b'}
 8 |               , { color: 'yellow', percent: '80', label: 'c'}
 9 |               ]
10 |        })
11 | 
12 | screen.append(donut)
13 | 
14 | screen.render()


--------------------------------------------------------------------------------
/examples/inline-data/gauge.js:
--------------------------------------------------------------------------------
1 | var blessed = require('blessed')
2 |   , contrib = require('../../')
3 |   , screen = blessed.screen()
4 |   , gauge = contrib.gauge({label: 'Progress', percent: 25})
5 |     
6 | screen.append(gauge)
7 | screen.render()


--------------------------------------------------------------------------------
/examples/inline-data/lcd.js:
--------------------------------------------------------------------------------
 1 | var blessed = require('blessed')
 2 |   , contrib = require('../../')
 3 |   , screen = blessed.screen()
 4 |   , grid = new contrib.grid({rows: 12, cols: 12, screen: screen})
 5 |   , map = grid.set(0, 0, 4, 4, contrib.map, {label: 'World Map'})
 6 |   , lcd = grid.set(4,4,4,4, contrib.lcd,
 7 |     {
 8 |       label: "LCD Test",
 9 |       segmentWidth: 0.06,
10 |       segmentInterval: 0.11,
11 |       strokeWidth: 0.1,
12 |       elements: 5,
13 |       display: 3210,
14 |       elementSpacing: 4,
15 |       elementPadding: 2
16 |     })
17 | 
18 | 
19 | screen.render()
20 |   
21 | 


--------------------------------------------------------------------------------
/examples/inline-data/map.js:
--------------------------------------------------------------------------------
 1 | var blessed = require('blessed')
 2 |   , contrib = require('../../')
 3 |   , screen = blessed.screen()
 4 |   , map = contrib.map({
 5 |       label: 'World Map',
 6 |       markers: 
 7 |          [ {"lon" : "-79.0000", "lat" : "37.5000", color: "red", char: "X" }
 8 |          , {"lon" : "79.0000", "lat" : "37.5000", color: "blue", char: "O" }
 9 |          ]
10 |    })
11 |     
12 | screen.append(map)
13 | 
14 | screen.render()


--------------------------------------------------------------------------------
/examples/inline-data/markdown.js:
--------------------------------------------------------------------------------
 1 | 
 2 | var blessed = require('blessed')
 3 |   , contrib = require('../../')
 4 |   , screen = blessed.screen()
 5 |   , chalk = require('chalk')
 6 |   , markdown = contrib.markdown({markdown: '# Hello \n blessed-contrib renders markdown using `marked-terminal` '
 7 |                                 , style: { firstHeading: 'chalk.green.italic' }})
 8 | 
 9 | screen.append(markdown)
10 | 
11 | screen.render()
12 | 


--------------------------------------------------------------------------------
/examples/inline-data/multi-line-chart.js:
--------------------------------------------------------------------------------
 1 | var blessed = require('blessed')
 2 | , contrib = require('../../index')
 3 | , screen = blessed.screen()
 4 | , line = contrib.line(
 5 |    { width: 80
 6 |    , height: 30
 7 |    , left: 15
 8 |    , top: 12  
 9 |    , xPadding: 5
10 |    , label: 'Title'
11 |    , showLegend: true
12 |    , legend: {width: 12}
13 |    , data: [ { title: 'us-east',
14 |              x: ['t1', 't2', 't3', 't4'],
15 |              y: [5, 1, 7, 5],
16 |              style: {
17 |               line: 'red'
18 |              }
19 |            }
20 |          , { title: 'us-west',
21 |              x: ['t1', 't2', 't3', 't4'],
22 |              y: [2, 4, 9, 8],
23 |              style: {line: 'yellow'}
24 |            }
25 |           , {title: 'eu-north-with-some-long-string', 
26 |              x: ['t1', 't2', 't3', 't4'],
27 |              y: [22, 7, 12, 1],
28 |              style: {line: 'blue'}
29 |            }]
30 | 
31 |    })
32 | 
33 | screen.append(line)
34 | 
35 | screen.key(['escape', 'q', 'C-c'], function(ch, key) {
36 |   return process.exit(0);
37 | });
38 | 
39 | screen.render()


--------------------------------------------------------------------------------
/examples/inline-data/sparkline.js:
--------------------------------------------------------------------------------
 1 | 
 2 | var blessed = require('blessed')
 3 |   , contrib = require('../../')
 4 |   , screen = blessed.screen()
 5 | 
 6 | var spark = contrib.sparkline(
 7 |      { label: 'Sparkline'
 8 |      , tags: true
 9 |      , border: {type: "line", fg: "cyan"} 
10 |      , width: '50%'
11 |      , height: '50%'
12 |      , style: { fg: 'blue' }
13 |      , data: { titles: [ 'Sparkline1', 'Sparkline2'], 
14 |                data: [ [10, 20, 30, 20, 50, 70, 60, 30, 35, 38]
15 |                      , [40, 10, 40, 50, 20, 30, 20, 20, 19, 40] ]
16 |              }
17 |       })
18 | 
19 | screen.append(spark)
20 | 
21 | screen.render()
22 | 
23 | 


--------------------------------------------------------------------------------
/examples/inline-data/table.js:
--------------------------------------------------------------------------------
 1 | var blessed = require('blessed')
 2 |   , contrib = require('../../')
 3 |   , screen = blessed.screen()
 4 | 
 5 | var table = contrib.table(
 6 |    { keys: true
 7 |    , fg: 'white'
 8 |    , interactive: false
 9 |    , label: 'Active Processes'
10 |    , width: '30%'
11 |    , height: '30%'
12 |    , border: {type: "line", fg: "cyan"}
13 |    , columnSpacing: 10
14 |    , columnWidth: [16, 12]
15 |    , data: { headers: ['col1', 'col2']
16 |            , data: [ [1, 2] 
17 |                    , [3, 4]
18 |                    , [5, 6] ]}
19 |     })
20 | 
21 | screen.append(table)
22 | 
23 | screen.key(['escape', 'q', 'C-c'], function(ch, key) {
24 |   return process.exit(0);
25 | });
26 | 
27 | screen.render()


--------------------------------------------------------------------------------
/examples/lcd.js:
--------------------------------------------------------------------------------
 1 | var blessed = require('blessed')
 2 |   , contrib = require('../')
 3 |   , screen = blessed.screen();
 4 |   
 5 | /*
 6 | //these options need to be modified epending on the resulting positioning/size
 7 |   options.segmentWidth = options.segmentWidth || 0.06; // how wide are the segments in % so 50% = 0.5
 8 |   options.segmentInterval = options.segmentInterval || 0.11; // spacing between the segments in % so 50% = 0.5
 9 |   options.strokeWidth = options.strokeWidth || 0.11; // spacing between the segments in % so 50% = 0.5
10 | 
11 | //default display settings
12 |   options.elements = options.elements || 3; // how many elements in the display. or how many characters can be displayed.
13 |   options.display = options.display || 321; // what should be displayed before anything is set
14 |   options.elementSpacing = options.spacing || 4; // spacing between each element
15 |   options.elementPadding = options.padding || 2; // how far away from the edges to put the elements
16 | 
17 | //coloring
18 |   options.color = options.color || "white";
19 | */
20 | 
21 | 
22 | var lcd = contrib.lcd({
23 | 	label: 'Test',
24 | 	elements: 4
25 | });
26 | 
27 | screen.append(lcd);
28 | 
29 | setInterval(function(){
30 | 	var colors = ['green','magenta','cyan','red','blue'];
31 | 	var text = ['A','B','C','D','E','F','G','H','I','J','K','L'];
32 | 
33 | 	var value = Math.round(Math.random() * 1000);
34 | 	lcd.setDisplay(value + text[value%12]);
35 | 	lcd.setOptions({
36 | 		color: colors[value%5],
37 | 		elementPadding: 5
38 | 	});
39 | 	screen.render();
40 | }, 1000);
41 | 
42 | screen.key(['g'], function(ch, key) {
43 | 	lcd.increaseWidth();
44 | 	screen.render();
45 | });
46 | screen.key(['h'], function(ch, key) {
47 | 	lcd.decreaseWidth();
48 | 	screen.render();
49 | });
50 | screen.key(['t'], function(ch, key) {
51 | 	lcd.increaseInterval();
52 | 	screen.render();
53 | });
54 | screen.key(['y'], function(ch, key) {
55 | 	lcd.decreaseInterval();
56 | 	screen.render();
57 | });
58 | screen.key(['b'], function(ch, key) {
59 | 	lcd.increaseStroke();
60 | 	screen.render();
61 | });
62 | screen.key(['n'], function(ch, key) {
63 | 	lcd.decreaseStroke();
64 | 	screen.render();
65 | });
66 | 
67 | screen.key(['escape', 'q', 'C-c'], function(ch, key) {
68 | 	return process.exit(0);
69 | });
70 | 
71 | screen.render()


--------------------------------------------------------------------------------
/examples/line-abbreviate.js:
--------------------------------------------------------------------------------
 1 | var blessed = require('blessed')
 2 | , contrib = require('../index')
 3 | , screen = blessed.screen()
 4 | , line = contrib.line(
 5 |    { width: 80
 6 |    , height: 30
 7 |    , left: 15
 8 |    , top: 12
 9 |    , xPadding: 5
10 |    , label: 'Title'
11 |    , abbreviate: true
12 |    , style: { baseline: 'white' }
13 |    })
14 | 
15 | , data = [ { title: 'us-east',
16 |              x: ['t1', 't2', 't3', 't4'],
17 |              y: [5, 8800, 99999, 3179000000],
18 |              style: {
19 |               line: 'red'
20 |              }
21 |            }
22 |         ]
23 | 
24 | 
25 | screen.append(line) //must append before setting data
26 | line.setData(data)
27 | 
28 | screen.key(['escape', 'q', 'C-c'], function(ch, key) {
29 |   return process.exit(0);
30 | });
31 | 
32 | screen.render()
33 | 


--------------------------------------------------------------------------------
/examples/line-fraction.js:
--------------------------------------------------------------------------------
 1 | var blessed = require('blessed')
 2 | , contrib = require('../index')
 3 | , screen = blessed.screen()
 4 | , line = contrib.line(
 5 |    { width: 80
 6 |    , height: 30
 7 |    , left: 15
 8 |    , top: 12
 9 |    , xPadding: 5
10 |    , label: 'Title'
11 |    , numYLabels: 7
12 |    //, wholeNumbersOnly: true
13 |    })
14 | 
15 | , data = [ { title: 'us-east',
16 |              x: ['t1', 't2', 't3', 't4'],
17 |              y: [0, 0.0695652173913043, 0.11304347826087, 2],
18 |              style: {
19 |               line: 'red'
20 |              }
21 |            }
22 |         ]
23 | 
24 | 
25 | screen.append(line) //must append before setting data
26 | line.setData(data)
27 | 
28 | screen.key(['escape', 'q', 'C-c'], function(ch, key) {
29 |   return process.exit(0);
30 | });
31 | 
32 | screen.render()
33 | 


--------------------------------------------------------------------------------
/examples/line-random-colors.js:
--------------------------------------------------------------------------------
 1 | var blessed = require('blessed')
 2 | , contrib = require('../index')
 3 | 
 4 | function randomColor() {
 5 |   return [Math.random() * 255,Math.random()*255, Math.random()*255]
 6 | }
 7 | 
 8 | var screen = blessed.screen()
 9 | , line = contrib.line(
10 |    { width: 80
11 |    , height: 30
12 |    , left: 15
13 |    , top: 12
14 |    , xPadding: 5
15 |    , minY: 30
16 |    , maxY: 90
17 |    , label: 'Title'
18 |    , style: { line: randomColor(), text: randomColor(), baseline: randomColor() }
19 |    })
20 | 
21 | , data = [ { title: 'us-east',
22 |              x: ['t1', 't2', 't3', 't4'],
23 |              y: [50, 88, 72, 91],
24 |              style: {
25 |               line: 'red'
26 |              }
27 |            }
28 |         ]
29 | 
30 | screen.append(line) //must append before setting data
31 | line.setData(data)
32 | 
33 | screen.key(['escape', 'q', 'C-c'], function(ch, key) {
34 |   return process.exit(0);
35 | });
36 | 
37 | screen.render()
38 | 


--------------------------------------------------------------------------------
/examples/line-start-above-zero.js:
--------------------------------------------------------------------------------
 1 | var blessed = require('blessed')
 2 | , contrib = require('../index')
 3 | , screen = blessed.screen()
 4 | , line = contrib.line(
 5 |    { width: 80
 6 |    , height: 30
 7 |    , left: 15
 8 |    , top: 12
 9 |    , xPadding: 5
10 |    , minY: 30
11 |    , label: 'Title'
12 |    , style: { baseline: 'white' }
13 |    })
14 | 
15 | , data = [ { title: 'us-east',
16 |              x: ['t1', 't2', 't3', 't4'],
17 |              y: [50, 88, 72, 91],
18 |              style: {
19 |               line: 'red'
20 |              }
21 |            }
22 |         ]
23 | 
24 | 
25 | screen.append(line) //must append before setting data
26 | line.setData(data)
27 | 
28 | screen.key(['escape', 'q', 'C-c'], function(ch, key) {
29 |   return process.exit(0);
30 | });
31 | 
32 | screen.render()
33 | 


--------------------------------------------------------------------------------
/examples/line-zoomed-in.js:
--------------------------------------------------------------------------------
 1 | var blessed = require('blessed')
 2 | , contrib = require('../index')
 3 | , screen = blessed.screen()
 4 | , line = contrib.line(
 5 |    { width: 80
 6 |    , height: 30
 7 |    , left: 15
 8 |    , top: 12
 9 |    , xPadding: 5
10 |    , minY: 1000
11 |    , maxY: 1050
12 |    , label: 'Title'
13 |    , style: { baseline: 'white' }
14 |    })
15 | 
16 | , data = [ { title: 'us-east',
17 |              x: ['t1', 't2', 't3', 't4'],
18 |              y: [1010, 1040, 1020, 1030],
19 |              style: {
20 |               line: 'red'
21 |              }
22 |            }
23 |         ]
24 | 
25 | 
26 | screen.append(line) //must append before setting data
27 | line.setData(data)
28 | 
29 | screen.key(['escape', 'q', 'C-c'], function(ch, key) {
30 |   return process.exit(0);
31 | });
32 | 
33 | screen.render()
34 | 


--------------------------------------------------------------------------------
/examples/log.js:
--------------------------------------------------------------------------------
 1 | var blessed = require('blessed')
 2 |   , contrib = require('../')
 3 |   , screen = blessed.screen()
 4 |   , log = contrib.log(
 5 |       { fg: "green"
 6 |       , label: 'Server Log'      
 7 |       , height: "20%"
 8 |       , tags: true      
 9 |       , border: {type: "line", fg: "cyan"} })
10 |     
11 | screen.append(log)
12 | 
13 | var i = 0
14 | setInterval(function() {log.log("new {red-fg}log{/red-fg} line " + i++)}, 500)
15 | 
16 | screen.render()
17 | 


--------------------------------------------------------------------------------
/examples/map.js:
--------------------------------------------------------------------------------
 1 | var blessed = require('blessed')
 2 |   , contrib = require('../')
 3 |   , screen = blessed.screen()
 4 |   , map = contrib.map({label: 'World Map'})
 5 |     
 6 | screen.append(map)
 7 | 
 8 | map.addMarker({"lon" : "-79.0000", "lat" : "37.5000", color: "red", char: "X" })
 9 | 
10 | screen.render()


--------------------------------------------------------------------------------
/examples/markdown.js:
--------------------------------------------------------------------------------
 1 | var blessed = require('blessed')
 2 |   , contrib = require('../')
 3 |   , screen = blessed.screen()
 4 |   , chalk = require('chalk')
 5 |   , markdown = contrib.markdown()
 6 |     
 7 | screen.append(markdown)
 8 | markdown.setOptions({ firstHeading: chalk.red.italic })
 9 | markdown.setMarkdown('# Hello \n This is **markdown** printed in the `terminal` 11')
10 | screen.render()


--------------------------------------------------------------------------------
/examples/marked-terminal.js:
--------------------------------------------------------------------------------
1 | const blessed = require("blessed")
2 | const contrib = require("../")
3 | 
4 | const screen = blessed.screen()
5 | const markdown = contrib.markdown()
6 | screen.append(markdown)
7 | markdown.setMarkdown("- [x] Checkbox")
8 | screen.render()
9 | 


--------------------------------------------------------------------------------
/examples/media/flower.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yaronn/blessed-contrib/ecd48d98c4c63a9cacfe20f68f568b3321ec46f5/examples/media/flower.png


--------------------------------------------------------------------------------
/examples/multi-line-chart.js:
--------------------------------------------------------------------------------
 1 | var blessed = require('blessed')
 2 | , contrib = require('../index')
 3 | , screen = blessed.screen()
 4 | , line = contrib.line(
 5 |    { width: 80
 6 |    , height: 30
 7 |    , left: 15
 8 |    , top: 12  
 9 |    , xPadding: 5
10 |    , label: 'Title'
11 |    , showLegend: true
12 |    , legend: {width: 12}})
13 | , data = [ { title: 'us-east',
14 |              x: ['t1', 't2', 't3', 't4'],
15 |              y: [5, 1, 7, 5],
16 |              style: {
17 |               line: 'red'
18 |              }
19 |            }
20 |          , { title: 'us-west',
21 |              x: ['t1', 't2', 't3', 't4'],
22 |              y: [2, 4, 9, 8],
23 |              style: {line: 'yellow'}
24 |            }
25 |           , {title: 'eu-north-with-some-long-string', 
26 |              x: ['t1', 't2', 't3', 't4'],
27 |              y: [22, 7, 12, 1],
28 |              style: {line: 'blue'}
29 |            }]
30 | 
31 | screen.append(line) //must append before setting data
32 | line.setData(data)
33 | 
34 | screen.key(['escape', 'q', 'C-c'], function(ch, key) {
35 |   return process.exit(0);
36 | });
37 | 
38 | screen.render()


--------------------------------------------------------------------------------
/examples/picture.js:
--------------------------------------------------------------------------------
 1 | var blessed = require('blessed')
 2 |   , contrib = require('../')
 3 |   , screen = blessed.screen()
 4 |     
 5 | var pic = contrib.picture(
 6 |    { file: './media/flower.png'
 7 |    , cols: 95
 8 |    , onReady: ready})
 9 | function ready() { screen.render() }
10 | 
11 | screen.append(pic)
12 | 
13 | 


--------------------------------------------------------------------------------
/examples/sparkline.js:
--------------------------------------------------------------------------------
 1 | 
 2 | var blessed = require('blessed')
 3 |   , contrib = require('../')
 4 |   , screen = blessed.screen()
 5 | 
 6 | var spark = contrib.sparkline(
 7 |      { label: 'Sparkline'
 8 |      , tags: true
 9 |      , border: {type: "line", fg: "cyan"} 
10 |      , width: '50%'
11 |      , height: '50%'
12 |      , style: { fg: 'blue' }})
13 | 
14 | screen.append(spark)
15 | 
16 | spark.setData(
17 |    [ 'Sparkline1', 'Sparkline2'], 
18 |    [ [10, 20, 30, 20, 50, 70, 60, 30, 35, 38]
19 |    , [40, 10, 40, 50, 20, 30, 20, 20, 19, 40]])
20 | 
21 | screen.render()
22 | 
23 | 


--------------------------------------------------------------------------------
/examples/stacked-bar.js:
--------------------------------------------------------------------------------
 1 | var blessed = require('blessed')
 2 |   , contrib = require('../')
 3 |   , screen = blessed.screen()
 4 |   , bar = contrib.stackedBar(
 5 |        { label: 'Server Utilization (%)'
 6 |        , barWidth: 4
 7 |        , barSpacing: 6
 8 |        , xOffset: 0
 9 |        //, maxValue: 15
10 |        , height: "40%"
11 |        , width: "50%"
12 |        , barBgColor: [ 'red', 'blue', 'green' ]})
13 | 
14 | screen.append(bar)
15 | 
16 | bar.setData(
17 |        { barCategory: ['Q1', 'Q2', 'Q3', 'Q4']
18 |        , stackedCategory: ['US', 'EU', 'AP']
19 |        , data:
20 |           [ [ 7, 7, 5]
21 |           , [8, 2, 0]
22 |           , [0, 0, 0]
23 |           , [2, 3, 2] ]
24 |        })
25 | 
26 | screen.render()
27 | 


--------------------------------------------------------------------------------
/examples/table-color.js:
--------------------------------------------------------------------------------
 1 | var blessed = require('blessed')
 2 |   , contrib = require('../')
 3 |   , screen = blessed.screen()
 4 |   , colors = require('colors/safe');
 5 | 
 6 | var table = contrib.table(
 7 |    { keys: true
 8 |    , fg: 'white'
 9 |    , selectedFg: 'white'
10 |    , selectedBg: 'blue'
11 |    , interactive: false
12 |    , label: 'Active Processes'
13 |    , width: '80%'
14 |    , height: '30%'
15 |    , border: {type: "line", fg: "cyan"}
16 |    , columnSpacing: 10
17 |    , columnWidth: [7, 12, 15]})
18 | 
19 | table.focus()
20 | screen.append(table)
21 | 
22 | table.setData(
23 |  { headers: ['col1', 'col2', 'col3']
24 |  , data:
25 |   [ [colors.blue('1111'), '22222', '55555']
26 |   , ['33333', '44444', '66666'] ]})
27 | 
28 | screen.key(['escape', 'q', 'C-c'], function(ch, key) {
29 |   return process.exit(0);
30 | });
31 | 
32 | screen.render()
33 | 


--------------------------------------------------------------------------------
/examples/table.js:
--------------------------------------------------------------------------------
 1 | var blessed = require('blessed')
 2 |   , contrib = require('../')
 3 |   , screen = blessed.screen()
 4 | 
 5 | var table = contrib.table(
 6 |    { keys: true
 7 |    , vi: true
 8 |    , fg: 'white'
 9 |    , selectedFg: 'white'
10 |    , selectedBg: 'blue'
11 |    , interactive: true
12 |    , label: 'Active Processes'
13 |    , width: '30%'
14 |    , height: '30%'
15 |    , border: {type: "line", fg: "cyan"}
16 |    , columnSpacing: 10
17 |    , columnWidth: [16, 12]})
18 | 
19 | table.focus()
20 | screen.append(table)
21 | 
22 | table.setData(
23 |  { headers: ['col1', 'col2']
24 |  , data:
25 |   [ [1, 2]
26 |   , [3, 4]
27 |   , [5, 6]
28 |   , [7, 8] ]})
29 | 
30 | screen.key(['escape', 'q', 'C-c'], function(ch, key) {
31 |   return process.exit(0);
32 | });
33 | 
34 | screen.render()
35 | 


--------------------------------------------------------------------------------
/index.d.ts:
--------------------------------------------------------------------------------
  1 | import * as Blessed from 'blessed'
  2 | export = BlessedContrib
  3 | declare namespace BlessedContrib {
  4 | 
  5 |     export type Optionals<T, K extends keyof T> = {
  6 |         [P in keyof K]?: T[K]
  7 |         }
  8 |     export type Picker<T, K extends keyof T> = {
  9 |         [P in K]: T[P];
 10 |         };
 11 | 
 12 | 
 13 |     export module Widgets {
 14 |         import IHasOptions = Blessed.Widgets.IHasOptions;
 15 |         import BoxOptions = Blessed.Widgets.BoxOptions;
 16 |         import ListOptions = Blessed.Widgets.ListOptions;
 17 |         import Types = Blessed.Widgets.Types;
 18 |         import ListElementStyle = Blessed.Widgets.ListElementStyle;
 19 |         import BoxElement = Blessed.Widgets.BoxElement;
 20 |         import ListElement = Blessed.Widgets.ListElement;
 21 | 
 22 |         export interface GridOptions {
 23 | 
 24 |             top?: Types.TTopLeft;
 25 |             left?: Types.TTopLeft;
 26 |             right?: Types.TPosition;
 27 |             bottom?: Types.TPosition;
 28 |             rows?: number
 29 |             cols?: number
 30 |             screen: Blessed.Widgets.Screen
 31 |             border?: Blessed.Widgets.Border
 32 |             hideBorder?: boolean
 33 |         }
 34 | 
 35 |         export type WidgetOptions =
 36 |             BoxOptions
 37 |             | BarOptions
 38 |             | StackedBarOptions
 39 |             | CanvasOptions
 40 |             | TreeOptions
 41 |             | TableOptions
 42 |             | PictureOptions
 43 |             | MarkdownOptions
 44 |             | MapOptions
 45 |             | SparklineOptions
 46 |             | LogOptions
 47 |             | LcdOptions
 48 |             | GaugeOptions
 49 |             | GaugeListOptions
 50 |             | DonutOptions
 51 | 
 52 | 
 53 |         export type WidgetElements = BoxElement
 54 |             | BarElement
 55 |             | LineElement
 56 |             | StackedBarElement
 57 |             | CanvasElement
 58 |             | TreeElement
 59 |             | TableElement
 60 |             | PictureElement
 61 |             | MarkdownElement
 62 |             | MapElement
 63 |             | SparklineElement
 64 |             | LogElement
 65 |             | LcdElement
 66 |             | GaugeElement
 67 |             | GaugeListElement
 68 |             | DonutElement
 69 | 
 70 | 
 71 |         export class GridElement extends BoxElement implements IHasOptions<GridOptions> {
 72 |             constructor(opts: GridOptions);
 73 | 
 74 |             set<T extends (options?: TreeOptions) => S, S extends TreeElement>(row: number, col: number, rowSpan: number, colSpan: number, obj: T, opt: TreeOptions): TreeElement
 75 |             set<T extends (options?: TableOptions) => S, S extends TableElement>(row: number, col: number, rowSpan: number, colSpan: number, obj: T, opt: TableOptions): TableElement
 76 |             set<T extends (options?: PictureOptions) => S, S extends PictureElement>(row: number, col: number, rowSpan: number, colSpan: number, obj: T, opt: PictureOptions): PictureElement
 77 |             set<T extends (options?: MarkdownOptions) => S, S extends MarkdownElement>(row: number, col: number, rowSpan: number, colSpan: number, obj: T, opt: MarkdownOptions): MarkdownElement
 78 |             set<T extends (options?: MapOptions) => S, S extends MapElement>(row: number, col: number, rowSpan: number, colSpan: number, obj: T, opt: MapOptions): MapElement
 79 |             set<T extends (options?: LogOptions) => S, S extends LogElement>(row: number, col: number, rowSpan: number, colSpan: number, obj: T, opt: LogOptions): LogElement
 80 |             set<T extends (options?: LcdOptions) => S, S extends LcdElement>(row: number, col: number, rowSpan: number, colSpan: number, obj: T, opt: LcdOptions): LcdElement
 81 |             set<T extends (options?: GaugeOptions) => S, S extends GaugeElement>(row: number, col: number, rowSpan: number, colSpan: number, obj: T, opt: GaugeOptions): GaugeElement
 82 |             set<T extends (options?: GaugeListOptions) => S, S extends GaugeListElement>(row: number, col: number, rowSpan: number, colSpan: number, obj: T, opt: GaugeListOptions): GaugeListElement
 83 |             set<T extends (options?: DonutOptions) => S, S extends DonutElement>(row: number, col: number, rowSpan: number, colSpan: number, obj: T, opt: DonutOptions): DonutElement
 84 | 
 85 |             set<T extends (options?: BarOptions) => S, S extends BarElement>(row: number, col: number, rowSpan: number, colSpan: number, obj: T, opt: BarOptions): BarElement
 86 |             set<T extends (options?: LineOptions) => S, S extends LineElement>(row: number, col: number, rowSpan: number, colSpan: number, obj: T, opt: LineOptions): LineElement
 87 |             set<T extends (options?: StackedBarOptions) => S, S extends StackedBarElement>(row: number, col: number, rowSpan: number, colSpan: number, obj: T, opt: StackedBarOptions): StackedBarElement
 88 |             set<T extends (options?: CanvasOptions) => S, S extends CanvasElement>(row: number, col: number, rowSpan: number, colSpan: number, obj: T, opt: CanvasOptions): CanvasElement
 89 | 
 90 | 
 91 |             // set<T extends (options?: WidgetOptions) => S, S extends WidgetElements>(row: number, col: number, rowSpan: number, colSpan: number, obj: T, opt: WidgetOptions): WidgetElements
 92 |             set<T, S>(...args:any[]): any
 93 | 
 94 |             // set<K extends keyof Factories>(row: number, col: number, rowSpan: number, colSpan: number,
 95 |             //     obj: T, opts?: P<T> ): P<T>
 96 |             // set<A =BarOptions, T=BarElement>(row: number, col: number, rowSpan: number, colSpan: number, obj: A, opts?: O): T //typeof bar
 97 |             // set<A =Line, T=LineElement>(row: number, col: number, rowSpan: number, colSpan: number, obj: A, opts?: O): T //typeof line
 98 |             // set<A =StackedBar, T=StackedBarElement>(row: number, col: number, rowSpan: number, colSpan: number, obj: A, opts?: O): T //typeof stackedBar
 99 |             // set<A =Canvas, T=CanvasElement>(row: number, col: number, rowSpan: number, colSpan: number, obj: A, opts?: O): T //typeof canvas
100 |             // set<A =Tree, T=TreeElement>(row: number, col: number, rowSpan: number, colSpan: number, obj: A, opts?: O): T //typeof tree
101 |             // set<A =Table, T=TableElement>(row: number, col: number, rowSpan: number, colSpan: number, obj: A, opts?: O): T //typeof table
102 |             // set<A =Picture, T=PictureElement>(row: number, col: number, rowSpan: number, colSpan: number, obj: A, opts?: O): T //typeof picture
103 |             // set<A =Markdown, T=MarkdownElement>(row: number, col: number, rowSpan: number, colSpan: number, obj: A, opts?: O): T //typeof markdown
104 |             // set<A =Map, T=MapElement>(row: number, col: number, rowSpan: number, colSpan: number, obj: A, opts?: O): T //typeof map
105 |             // set<A =Log, T=LogElement>(row: number, col: number, rowSpan: number, colSpan: number, obj: A, opts?: O): T //typeof log
106 |             // set<A =Lcd, T=LcdElement>(row: number, col: number, rowSpan: number, colSpan: number, obj: A, opts?: O): T //typeof lcd
107 |             // set<A =Gauge, T=GaugeElement>(row: number, col: number, rowSpan: number, colSpan: number, obj: A, opts?: O): T //typeof gauge
108 |             // set<A =GaugeList, T=GaugeListElement>(row: number, col: number, rowSpan: number, colSpan: number, obj: A, opts?: O): T //typeof gaugeList
109 |             // set<A =Donut, T=DonutElement>(row: number, col: number, rowSpan: number, colSpan: number, obj: A, opts?: O): T //typeof donut
110 | 
111 |             options: GridOptions;
112 |         }
113 | 
114 | 
115 |         export interface BarData {
116 |             titles?: string[],
117 |             data?: number[]
118 |         }
119 | 
120 |         export interface BarOptions extends CanvasOptions<BarData> {
121 |             barWidth?: number
122 |             barSpacing?: number
123 |             xOffset?: number
124 |             maxHeight?: number
125 |             showText?: boolean
126 |             barBgColor?: string
127 |             barFgColor?: string
128 |         }
129 | 
130 | 
131 |         export class BarElement extends CanvasElement<BarData> implements IHasOptions<BarOptions> {
132 |             constructor(opts: BarOptions);
133 | 
134 |             setData(data: BarData): void;
135 | 
136 |             options: BarOptions;
137 |         }
138 | 
139 | 
140 |         export interface LineData {
141 |             title?: string
142 |             x?: string[]
143 |             y?: number[]
144 |             style?: {
145 |                 line?: string
146 |                 text?: string
147 |                 baseline?: string
148 |             }
149 |         }
150 | 
151 |         export interface LineOptions extends CanvasOptions<LineData[]> {
152 |             showNthLabel?: boolean
153 |             style?: {
154 |                 line?: string
155 |                 text?: string
156 |                 baseline?: string
157 |             }
158 |             xLabelPadding?: number
159 |             xPadding?: number
160 |             numYLabels?: number
161 |             legend?: { width: number }
162 |             wholeNumbersOnly?: boolean
163 |             minY?: number
164 |             maxY?: number
165 |             label?: string
166 |         }
167 | 
168 |         export class LineElement extends CanvasElement<LineData[]> implements IHasOptions<LineOptions> {
169 |             constructor(opts: LineOptions);
170 | 
171 |             options: LineOptions;
172 |         }
173 | 
174 |         export interface StackedBarData {
175 |             barCategory?: string[]
176 |             stackedCategory?: string[]
177 |             data?: Array<number[]>
178 |         }
179 | 
180 |         export interface StackedBarOptions extends CanvasOptions<StackedBarData[]> {
181 | 
182 |             barWidth?: number
183 |             barSpacing?: number
184 |             xOffset?: number
185 |             maxValue?: number
186 |             barBgColor?: string
187 |             showLegend?: boolean
188 |             legend?: any
189 |             showText?: boolean
190 |         }
191 | 
192 |         export class StackedBarElement extends CanvasElement<StackedBarData[]> implements IHasOptions<StackedBarOptions> {
193 |             constructor(opts: StackedBarOptions)
194 | 
195 |             options: StackedBarOptions;
196 | 
197 |             addLegend(bars: any, x: number): void;
198 |         }
199 | 
200 | 
201 |         export interface CanvasOptions<D extends any=any>  extends BoxOptions {
202 |             canvasSize?: {
203 |                 width?: number,
204 |                 height?: number
205 |             }
206 |             data?: D
207 |         }
208 | 
209 |         export class CanvasElement<D extends any=any> extends BoxElement implements IHasOptions<CanvasOptions> {
210 |             constructor(opts: CanvasOptions<D>)
211 | 
212 |             options: CanvasOptions<D>;
213 | 
214 |             calcSize(): void;
215 | 
216 |             setData(data: D): void;
217 |             setData(titles: string[], data: D): void;
218 | 
219 |             canvasSize: { width: number, height: number }
220 |         }
221 | 
222 |         export interface DonutData {
223 |             percent?: string,
224 |             label?: string,
225 |             color?: string
226 |         }
227 | 
228 |         export interface DonutOptions extends CanvasOptions<DonutData[]> {
229 |             stroke?: string
230 |             fill?: string
231 |             label?: string
232 |             radius?: number
233 |             arcWidth?: number
234 |             spacing?: number
235 |             remainColor?: string
236 |             yPadding?: number
237 | 
238 | 
239 |         }
240 | 
241 |         export class DonutElement extends CanvasElement<DonutData[]> implements IHasOptions<DonutOptions> {
242 |             constructor(opts: DonutOptions)
243 | 
244 |             options: DonutOptions;
245 | 
246 |         }
247 | 
248 | 
249 |         export interface GaugeListOptions extends CanvasOptions {
250 |         }
251 | 
252 |         export class GaugeListElement extends CanvasElement implements IHasOptions<GaugeListOptions> {
253 |             constructor(opts: GaugeListOptions)
254 | 
255 |             options: GaugeListOptions;
256 |         }
257 | 
258 | 
259 |         export interface GaugeOptions extends CanvasOptions {
260 |             percent: number[]
261 |             stroke?: string
262 |             fill?: string
263 |             label?: string
264 |             stack?: any
265 |             showLabel?: boolean
266 |         }
267 | 
268 |         export class GaugeElement extends CanvasElement implements IHasOptions<GaugeOptions> {
269 |             constructor(opts: GaugeOptions)
270 | 
271 |             options: GaugeOptions;
272 | 
273 |             setPercent(number: number): void;
274 | 
275 |             setStack(stack: Array<{ percent: number, stroke: string }>): void;
276 | 
277 |             setData(percent: number[]): void;
278 |             setData(percent: number): void;
279 |         }
280 | 
281 | 
282 |         export interface LcdOptions extends CanvasOptions {
283 |             segmentWidth?: number// how wide are the segments in % so 50% = 0.5
284 |             segmentInterval?: number// spacing between the segments in % so 50% = 0.550% = 0.5
285 |             strokeWidth?: number// spacing between the segments in % so 50% = 0.5
286 |             elements?: number// how many elements in the display. or how many characters can be displayed.
287 |             display?: number// what should be displayed before first call to setDisplay
288 |             elementSpacing?: number// spacing between each element
289 |             elementPadding?: number// how far away from the edges to put the elements
290 |             color?: 'white' // color for the segments
291 |             label?: 'Storage Remaining'
292 |         }
293 | 
294 |         export class LcdElement extends CanvasElement implements IHasOptions<LcdOptions> {
295 |             constructor(opts: LcdOptions)
296 | 
297 |             options: LcdOptions;
298 | 
299 |             increaseWidth(): void;
300 | 
301 |             decreaseWidth(): void;
302 | 
303 |             increaseInterval(): void;
304 | 
305 |             decreaseInterval(): void;
306 | 
307 |             increaseStroke(): void;
308 | 
309 |             decreaseStroke(): void;
310 | 
311 |             setOptions(options: any): void;
312 | 
313 |             setDisplay(display: any): void;
314 |         }
315 | 
316 |         export interface LogOptions extends ListOptions<ListElementStyle> {
317 |             border: Blessed.Widgets.Border
318 |             bufferLength?: number
319 |             logLines?: string[]
320 |             interactive?: boolean
321 |         }
322 | 
323 |         export class LogElement extends ListElement implements IHasOptions<LogOptions> {
324 |             constructor(opts: LogOptions);
325 | 
326 |             options: LogOptions;
327 | 
328 |             log(str: string): boolean;
329 | 
330 |             emit(str:any): boolean;
331 |         }
332 | 
333 | 
334 |         export interface MapOptions extends CanvasOptions {
335 |         }
336 | 
337 |         export class MapElement extends CanvasElement implements IHasOptions<MapOptions> {
338 |             constructor(opts: MapOptions)
339 | 
340 |             options: MapOptions;
341 |         }
342 | 
343 | 
344 |         export interface SparklineOptions extends CanvasOptions<string[]> {
345 |         }
346 | 
347 |         export class SparklineElement extends CanvasElement<string[]> implements IHasOptions<SparklineOptions> {
348 |             constructor(opts: CanvasOptions);
349 | 
350 |             options: SparklineOptions;
351 | 
352 |             setData(...str: any[]): void;
353 |         }
354 | 
355 |         export interface MarkdownOptions extends CanvasOptions {
356 |           /** 
357 |            * Markdown text to render.
358 |            */
359 |           markdown?: string;
360 | 
361 |           markdownStyle?: any;
362 |         }
363 | 
364 |         export class MarkdownElement extends CanvasElement implements IHasOptions<MarkdownOptions> {
365 |             constructor(opts: MarkdownOptions)
366 | 
367 |             options: MarkdownOptions;
368 | 
369 |             setOptions(options: any): void;
370 | 
371 |             setMarkdown(markdown: string): void;
372 |         }
373 | 
374 | 
375 |         export interface PictureOptions extends CanvasOptions {
376 |         }
377 | 
378 |         export class PictureElement extends CanvasElement implements IHasOptions<PictureOptions> {
379 |             constructor(opts: PictureOptions)
380 | 
381 |             options: PictureOptions;
382 |         }
383 | 
384 |         export interface TableData {
385 |             headers?: string[]
386 |             data?: Array<string[]>
387 |         }
388 | 
389 |         export interface TableOptions extends CanvasOptions<TableData> {
390 |             parent?: any
391 |             bold?: string
392 |             columnSpacing?: number
393 |             columnWidth?: number[]
394 |             rows?: ListOptions<ListElementStyle>
395 |             selectedFg?: string
396 |             selectedBg?: string
397 |             label?: string
398 |             fg?: string
399 |             bg?: string
400 |             width?: string
401 |             height?: string
402 |             border?: object
403 |             interactive?: string
404 |         }
405 | 
406 |         export class TableElement extends CanvasElement<TableData> implements IHasOptions<TableOptions> {
407 |             constructor(opts: TableOptions);
408 | 
409 |             options: TableOptions;
410 |         }
411 | 
412 | 
413 |         export interface TreeNode {
414 |             name?: string,
415 |             children?: TreeChildren | ((node: TreeNode) => TreeChildren | Promise<TreeChildren>),
416 |             childrenContent?: TreeChildren,
417 |             extended?: boolean,
418 |             parent?: TreeNode,
419 |             [custom: string]: any
420 |         }
421 | 
422 |         export type TreeChildren = Record<string, TreeNode>
423 | 
424 |         export interface TreeOptions extends BoxOptions {
425 |             data?: any
426 |             extended?: boolean
427 |             keys?: string[]
428 |             template?: {
429 |                 extend?: string
430 |                 retract?: string
431 |                 lines?: boolean
432 |             }
433 |         }
434 | 
435 |         export class TreeElement extends BoxElement implements IHasOptions<TreeOptions> {
436 |             constructor(opts: TreeOptions)
437 | 
438 |             rows: Blessed.Widgets.ListElement
439 |             nodeLines?: string[]
440 |             lineNbr?: number
441 |             data: any
442 | 
443 |             options: TreeOptions;
444 | 
445 |             setData(data: TreeNode): void
446 |         }
447 | 
448 | 
449 |     }
450 | 
451 |     export module widget {
452 | 
453 |         export class Grid extends Widgets.GridElement {}
454 | 
455 |         export class Bar extends Widgets.BarElement {}
456 | 
457 |         export class Line extends Widgets.LineElement {}
458 | 
459 |         export class StackedBar extends Widgets.StackedBarElement {}
460 | 
461 |         export class Canvas extends Widgets.CanvasElement {}
462 | 
463 |         export class Tree extends Widgets.TreeElement {}
464 | 
465 |         export class Table extends Widgets.TableElement {}
466 | 
467 |         export class Picture extends Widgets.PictureElement {}
468 | 
469 |         export class Markdown extends Widgets.MarkdownElement {}
470 | 
471 |         export class Map extends Widgets.MapElement {}
472 | 
473 |         export class Log extends Widgets.LogElement {}
474 | 
475 |         export class Lcd extends Widgets.LcdElement {}
476 | 
477 |         export class Gauge extends Widgets.GaugeElement {}
478 | 
479 |         export class GaugeList extends Widgets.GaugeListElement {}
480 | 
481 |         export class Donut extends Widgets.DonutElement {}
482 | 
483 |         export class Sparkline extends Widgets.SparklineElement {}
484 | 
485 |     }
486 | 
487 | 
488 |     export class grid extends Widgets.GridElement {}
489 | 
490 |     export function line(options?: Widgets.LineOptions): Widgets.LineElement
491 | 
492 |     export function bar(options?: Widgets.BarOptions): Widgets.BarElement
493 | 
494 |     export function stackedBar(options?: Widgets.StackedBarOptions): Widgets.StackedBarElement
495 | 
496 |     export function canvas(options?: Widgets.CanvasOptions): Widgets.CanvasElement
497 | 
498 |     export function tree(options?: Widgets.TreeOptions): Widgets.TreeElement
499 | 
500 |     export function table(options?: Widgets.TableOptions): Widgets.TableElement
501 | 
502 |     export function picture(options?: Widgets.PictureOptions): Widgets.PictureElement
503 | 
504 |     export function markdown(options?: Widgets.MarkdownOptions): Widgets.MarkdownElement
505 | 
506 |     export function sparkline(options?: Widgets.SparklineOptions): Widgets.SparklineElement
507 | 
508 |     export function map(options?: Widgets.MapOptions): Widgets.MapElement
509 | 
510 |     export function log(options?: Widgets.LogOptions): Widgets.LogElement
511 | 
512 |     export function lcd(options?: Widgets.LcdOptions): Widgets.LcdElement
513 | 
514 |     export function gauge(options?: Widgets.GaugeOptions): Widgets.GaugeElement
515 | 
516 |     export function gaugeList(options?: Widgets.GaugeListOptions): Widgets.GaugeListElement
517 | 
518 |     export function donut(options?: Widgets.DonutOptions): Widgets.DonutElement
519 | 
520 | }
521 | 
522 | 


--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
 1 | 
 2 | exports.grid = require('./lib/layout/grid')
 3 | exports.carousel = require('./lib/layout/carousel')
 4 | 
 5 | exports.map = require('./lib/widget/map')
 6 | exports.canvas = require('./lib/widget/canvas')
 7 | 
 8 | exports.gauge = require('./lib/widget/gauge.js')
 9 | exports.gaugeList = require('./lib/widget/gauge-list.js')
10 | 
11 | exports.lcd = require('./lib/widget/lcd.js')
12 | exports.donut = require('./lib/widget/donut.js')
13 | exports.log = require('./lib/widget/log.js')
14 | exports.picture = require('./lib/widget/picture.js')
15 | exports.sparkline = require('./lib/widget/sparkline.js')
16 | exports.table = require('./lib/widget/table.js')
17 | exports.tree = require('./lib/widget/tree.js')
18 | exports.markdown = require('./lib/widget/markdown.js')
19 | 
20 | exports.bar = require('./lib/widget/charts/bar')
21 | exports.stackedBar = require('./lib/widget/charts/stacked-bar')
22 | exports.line = require('./lib/widget/charts/line')
23 | 
24 | exports.OutputBuffer = require('./lib/server-utils').OutputBuffer
25 | exports.InputBuffer = require('./lib/server-utils').InputBuffer
26 | exports.createScreen = require('./lib/server-utils').createScreen
27 | exports.serverError = require('./lib/server-utils').serverError
28 | 


--------------------------------------------------------------------------------
/lib/layout/carousel.js:
--------------------------------------------------------------------------------
 1 | 'use strict';
 2 | function Carousel(pages, options) {
 3 |   this.currPage = 0;
 4 |   this.pages = pages;
 5 |   this.options = options;
 6 |   this.screen = this.options.screen;
 7 | }
 8 | 
 9 | Carousel.prototype.move = function() {
10 |   var i = this.screen.children.length;
11 |   while (i--) this.screen.children[i].detach();
12 | 
13 |   this.pages[this.currPage](this.screen, this.currPage);
14 |   this.screen.render();
15 | };
16 | 
17 | Carousel.prototype.next = function() {
18 |   this.currPage++;
19 |   if (this.currPage==this.pages.length){
20 |     if (!this.options.rotate) {
21 |       this.currPage--;
22 |       return;
23 |     } else {
24 |       this.currPage=0;
25 |     }
26 |   }
27 |   this.move();
28 | };
29 | 
30 | Carousel.prototype.prev = function() {
31 |   this.currPage--;
32 |   if (this.currPage<0) {
33 |     if (!this.options.rotate) {
34 |       this.currPage++;
35 |       return;
36 |     } else {
37 |       this.currPage=this.pages.length-1;
38 |     }
39 |   }
40 |   this.move();
41 | };
42 | 
43 | Carousel.prototype.home = function() {
44 |   this.currPage = 0;
45 |   this.move();
46 | };
47 | 
48 | Carousel.prototype.end = function() {
49 |   this.currPage = this.pages.length -1;
50 |   this.move();
51 | };
52 | 
53 | Carousel.prototype.start = function() {
54 |   var self = this;
55 | 
56 |   this.move();
57 | 
58 |   if (this.options.interval) {
59 |     setInterval(this.next.bind(this), this.options.interval);
60 |   }
61 | 
62 |   if (this.options.controlKeys) {
63 |     this.screen.key(['right', 'left', 'home', 'end'], function(ch, key) {
64 |       if (key.name=='right') self.next();
65 |       if (key.name=='left') self.prev();
66 |       if (key.name=='home') self.home();
67 |       if (key.name=='end') self.end();
68 |     });
69 |   }
70 | 
71 | };
72 | 
73 | module.exports = Carousel;
74 | 


--------------------------------------------------------------------------------
/lib/layout/grid.js:
--------------------------------------------------------------------------------
 1 | 'use strict';
 2 | var utils = require('../utils');
 3 | 
 4 | var widgetSpacing = 0;
 5 | 
 6 | function Grid(options) {
 7 |   if (!options.screen) throw 'Error: A screen property must be specified in the grid options.\r\n' +
 8 |                               'Note: Release 2.0.0 has breaking changes. Please refer to the README or to https://github.com/yaronn/blessed-contrib/issues/39';
 9 |   this.options = options;
10 |   this.options.dashboardMargin = this.options.dashboardMargin || 0;
11 |   this.cellWidth = ((100 - this.options.dashboardMargin*2) / this.options.cols);
12 |   this.cellHeight = ((100  - this.options.dashboardMargin*2) / this.options.rows);
13 | }
14 | 
15 | Grid.prototype.set = function(row, col, rowSpan, colSpan, obj, opts) {
16 | 
17 |   if (obj instanceof Grid) {
18 |     throw 'Error: A Grid is not allowed to be nested inside another grid.\r\n' +
19 |             'Note: Release 2.0.0 has breaking changes. Please refer to the README or to https://github.com/yaronn/blessed-contrib/issues/39';
20 |   }
21 | 
22 |   var top = row * this.cellHeight + this.options.dashboardMargin;
23 |   var left = col * this.cellWidth + this.options.dashboardMargin;
24 | 
25 |   //var options = JSON.parse(JSON.stringify(opts));
26 |   var options = {};
27 |   options = utils.MergeRecursive(options, opts);
28 |   options.top = top + '%';
29 |   options.left = left + '%';
30 |   options.width = (this.cellWidth * colSpan - widgetSpacing) + '%';
31 |   options.height = (this.cellHeight * rowSpan - widgetSpacing) + '%';
32 |   if (!this.options.hideBorder)
33 |     options.border = {type: 'line', fg: this.options.color || 'cyan'};
34 | 
35 |   var instance = obj(options);
36 |   this.options.screen.append(instance);
37 |   return instance;
38 | };
39 | 
40 | module.exports = Grid;
41 | 


--------------------------------------------------------------------------------
/lib/server-utils.js:
--------------------------------------------------------------------------------
 1 | 'use strict';
 2 | var url = require('url')
 3 |   , contrib = require('../index')
 4 |   , blessed = require('blessed');
 5 | 
 6 | function OutputBuffer(options) {
 7 |   this.isTTY = true;
 8 |   this.columns = options.cols;
 9 |   this.rows = options.rows;
10 |   this.write = function(s) {
11 |     s = s.replace('\x1b8', ''); //not clear from where in blessed this code comes from. It forces the terminal to clear and loose existing content.
12 |     options.res.write(s);
13 |   };
14 | 
15 |   this.on = function() {};
16 | }
17 | 
18 | function InputBuffer() {
19 |   this.isTTY = true;
20 |   this.isRaw = true;
21 | 
22 |   this.emit = function() {};
23 | 
24 |   this.setRawMode = function() {};
25 |   this.resume = function() {};
26 |   this.pause = function() {};
27 | 
28 |   this.on = function() {};
29 | }
30 | 
31 | function serverError(req, res, err) {
32 |   setTimeout(function() {
33 |     if (!res.headersSent) res.writeHead(500, {'Content-Type': 'text/plain'});
34 |     res.write('\r\n\r\n'+err+'\r\n\r\n');
35 |     //restore cursor
36 |     res.end('\u001b[?25h');
37 |   }, 0);
38 | 
39 |   return true;
40 | }
41 | 
42 | 
43 | function createScreen(req, res) {
44 |   var query = url.parse(req.url, true).query;
45 | 
46 |   var cols = query.cols || 250;
47 |   var rows = query.rows || 50;
48 | 
49 |   if (cols<=35 || cols>=500 || rows<=5 || rows>=300) {
50 |     serverError(req, res, 'cols must be bigger than 35 and rows must be bigger than 5');
51 |     return null;
52 |   }
53 | 
54 |   res.writeHead(200, {'Content-Type': 'text/plain'});
55 | 
56 |   var output = new contrib.OutputBuffer({res: res, cols: cols, rows: rows});
57 |   var input = new contrib.InputBuffer(); //required to run under forever since it replaces stdin to non-tty
58 |   var program = blessed.program({output: output, input: input});
59 | 
60 |   if (query.terminal) program.terminal = query.terminal;
61 |   if (query.isOSX) program.isOSXTerm = query.isOSX;
62 |   if (query.isiTerm2) program.isiTerm2 = query.isiTerm2;
63 | 
64 |   var screen = blessed.screen({program: program});
65 |   return screen;
66 | }
67 | 
68 | 
69 | exports.createScreen = createScreen;
70 | exports.OutputBuffer = OutputBuffer;
71 | exports.InputBuffer = InputBuffer;
72 | exports.serverError = serverError;
73 | 


--------------------------------------------------------------------------------
/lib/utils.js:
--------------------------------------------------------------------------------
 1 | 'use strict';
 2 | var x256 = require('x256');
 3 | 
 4 | /*
 5 | * Recursively merge properties of two objects
 6 | */
 7 | function MergeRecursive(obj1, obj2) {
 8 |   if (obj1==null) {
 9 |     return obj2;
10 |   }
11 |   if (obj2==null) {
12 |     return obj1;
13 |   }
14 | 
15 |   for (var p in obj2) {
16 |     try {
17 |       // property in destination object set; update its value
18 |       if ( obj2[p].constructor==Object ) {
19 |         obj1[p] = MergeRecursive(obj1[p], obj2[p]);
20 | 
21 |       } else {
22 |         obj1[p] = obj2[p];
23 | 
24 |       }
25 | 
26 |     } catch(e) {
27 |       // property in destination object not set; create it and set its value
28 |       obj1[p] = obj2[p];
29 | 
30 |     }
31 |   }
32 | 
33 |   return obj1;
34 | }
35 | 
36 | 
37 | function getTypeName(thing){
38 |   if(thing===null)return '[object Null]'; // special case
39 |   return Object.prototype.toString.call(thing);
40 | }
41 | 
42 | function abbreviateNumber(value) {
43 |   var newValue = value;
44 |   if (value >= 1000) {
45 |     var suffixes = ['', 'k', 'm', 'b','t'];
46 |     var suffixNum = Math.floor( (''+value).length/3 );
47 |     var shortValue = '';
48 |     for (var precision = 2; precision >= 1; precision--) {
49 |       shortValue = parseFloat( (suffixNum != 0 ? (value / Math.pow(1000,suffixNum) ) : value).toPrecision(precision));
50 |       var dotLessShortValue = (shortValue + '').replace(/[^a-zA-Z 0-9]+/g,'');
51 |       if (dotLessShortValue.length <= 2) {
52 |         break;
53 |       }
54 |     }
55 |     newValue = shortValue+suffixes[suffixNum];
56 |   }
57 |   return newValue;
58 | }
59 | 
60 | function getColorCode(color) {
61 |   if (Array.isArray(color) && color.length == 3) {
62 |     return x256(color[0],color[1],color[2]);
63 |   } else {
64 |     return color;
65 |   }
66 | }
67 | 
68 | exports.MergeRecursive = MergeRecursive;
69 | exports.getTypeName = getTypeName;
70 | exports.abbreviateNumber = abbreviateNumber;
71 | exports.getColorCode = getColorCode;
72 | 
73 | 


--------------------------------------------------------------------------------
/lib/widget/canvas.js:
--------------------------------------------------------------------------------
 1 | 'use strict';
 2 | var blessed = require('blessed')
 3 |   , Node = blessed.Node
 4 |   , Box = blessed.Box
 5 |   , InnerCanvas = require('drawille-canvas-blessed-contrib').Canvas;
 6 | 
 7 | function Canvas(options, canvasType) {
 8 | 
 9 |   var self = this;
10 | 
11 |   if (!(this instanceof Node)) {
12 |     return new Canvas(options);
13 |   }
14 | 
15 |   options = options || {};
16 |   this.options = options;
17 |   Box.call(this, options);
18 | 
19 |   this.on('attach', function() {
20 |     self.calcSize();
21 | 
22 |     self._canvas = new InnerCanvas(this.canvasSize.width, this.canvasSize.height, canvasType);
23 |     self.ctx = self._canvas.getContext();
24 | 
25 |     if (self.options.data) {
26 |       self.setData(self.options.data);
27 |     }
28 |   });
29 | }
30 | 
31 | Canvas.prototype = Object.create(Box.prototype);
32 | 
33 | Canvas.prototype.type = 'canvas';
34 | 
35 | Canvas.prototype.calcSize = function() {
36 |   this.canvasSize = {width: this.width*2-12, height: this.height*4};
37 | };
38 | 
39 | Canvas.prototype.clear = function() {
40 |   this.ctx.clearRect(0, 0, this.canvasSize.width, this.canvasSize.height);
41 | };
42 | 
43 | Canvas.prototype.render = function() {
44 | 
45 |   this.clearPos(true);
46 |   var inner = this.ctx._canvas.frame();
47 |   this.setContent(inner);
48 |   return this._render();
49 | };
50 | 
51 | module.exports = Canvas;
52 | 


--------------------------------------------------------------------------------
/lib/widget/charts/bar.js:
--------------------------------------------------------------------------------
 1 | 'use strict';
 2 | var blessed = require('blessed')
 3 |   , Node = blessed.Node
 4 |   , Canvas = require('../canvas');
 5 | 
 6 | function Bar(options) {
 7 |   if (!(this instanceof Node)) {
 8 |     return new Bar(options);
 9 |   }
10 | 
11 |   var self = this;
12 | 
13 |   Canvas.call(this, options, require('ansi-term'));
14 | 
15 |   this.options.barWidth = this.options.barWidth || 6;
16 |   this.options.barSpacing = this.options.barSpacing || 9;
17 | 
18 |   if ((this.options.barSpacing - this.options.barWidth) < 3) {
19 |     this.options.barSpacing = this.options.barWidth + 3;
20 |   }
21 | 
22 |   this.options.xOffset = this.options.xOffset==null? 5 : this.options.xOffset;
23 |   if (this.options.showText === false)
24 |     this.options.showText = false;
25 |   else
26 |     this.options.showText = true;
27 | 
28 |   this.on('attach', function() {
29 |     if (self.options.data) {
30 |       self.setData(self.options.data);
31 |     }
32 |   });
33 | }
34 | 
35 | Bar.prototype = Object.create(Canvas.prototype);
36 | 
37 | Bar.prototype.calcSize = function() {
38 |   this.canvasSize = {width: this.width-2, height: this.height};
39 | };
40 | 
41 | Bar.prototype.setData = function(bar) {
42 | 
43 |   if (!this.ctx) {
44 |     throw 'error: canvas context does not exist. setData() for bar charts must be called after the chart has been added to the screen via screen.append()';
45 |   }
46 | 
47 |   this.clear();
48 | 
49 |   var c = this.ctx;
50 |   var max = Math.max.apply(Math, bar.data);
51 |   max = Math.max(max, this.options.maxHeight);
52 |   var x = this.options.xOffset;
53 |   var barY = this.canvasSize.height - 5;
54 | 
55 |   for (var i = 0; i < bar.data.length; i++) {
56 |     var h = Math.round(barY * (bar.data[i] / max));
57 | 
58 |     if (bar.data[i] > 0) {
59 |       c.strokeStyle = 'blue';
60 |       if (this.options.barBgColor)
61 |         c.strokeStyle = this.options.barBgColor;
62 |       c.fillRect(x, barY - h + 1, this.options.barWidth, h);
63 |     } else {
64 |       c.strokeStyle = 'normal';
65 |     }
66 | 
67 |     c.fillStyle = 'white';
68 |     if (this.options.barFgColor)
69 |       c.fillStyle = this.options.barFgColor;
70 |     if (this.options.showText)
71 |       c.fillText(bar.data[i].toString(), x + 1, this.canvasSize.height - 4);
72 |     c.strokeStyle = 'normal';
73 |     c.fillStyle = 'white';
74 |     if (this.options.labelColor)
75 |       c.fillStyle = this.options.labelColor;
76 |     if (this.options.showText)
77 |       c.fillText(bar.titles[i], x + 1, this.canvasSize.height - 3);
78 | 
79 |     x += this.options.barSpacing;
80 |   }
81 | };
82 | 
83 | Bar.prototype.getOptionsPrototype = function() {
84 |   return  {  barWidth: 1
85 |     ,  barSpacing: 1
86 |     ,  xOffset: 1
87 |     ,  maxHeight: 1
88 |     ,  data: { titles: ['s']
89 |       , data: [1]}
90 |   };
91 | };
92 | 
93 | Bar.prototype.type = 'bar';
94 | 
95 | module.exports = Bar;
96 | 


--------------------------------------------------------------------------------
/lib/widget/charts/line.js:
--------------------------------------------------------------------------------
  1 | 'use strict';
  2 | var blessed = require('blessed')
  3 |   , Node = blessed.Node
  4 |   , Canvas = require('../canvas')
  5 |   , utils = require('../../utils.js')
  6 |   , _ = require('lodash');
  7 | 
  8 | function Line(options) {
  9 |   if (!(this instanceof Node)) {
 10 |     return new Line(options);
 11 |   }
 12 | 
 13 |   options.showNthLabel = options.showNthLabel || 1;
 14 |   options.style = options.style || {};
 15 |   options.style.line = options.style.line || 'yellow';
 16 |   options.style.text = options.style.text || 'green';
 17 |   options.style.baseline = options.style.baseline || 'black';
 18 |   options.xLabelPadding = options.xLabelPadding || 5;
 19 |   options.xPadding = options.xPadding || 10;
 20 |   options.numYLabels = options.numYLabels || 5;
 21 |   options.legend = options.legend || {};
 22 |   options.wholeNumbersOnly = options.wholeNumbersOnly || false;
 23 |   options.minY = options.minY || 0;
 24 | 
 25 |   Canvas.call(this, options);
 26 | }
 27 | 
 28 | Line.prototype = Object.create(Canvas.prototype);
 29 | 
 30 | Line.prototype.calcSize = function() {
 31 |   this.canvasSize = {width: this.width*2-12, height: this.height*4-8};
 32 | };
 33 | 
 34 | Line.prototype.type = 'line';
 35 | 
 36 | Line.prototype.setData = function(data) {
 37 | 
 38 |   if (!this.ctx) {
 39 |     throw 'error: canvas context does not exist. setData() for line charts must be called after the chart has been added to the screen via screen.append()';
 40 |   }
 41 | 
 42 |   //compatability with older api
 43 |   if (!Array.isArray(data)) data = [data];
 44 | 
 45 |   var self = this;
 46 |   var xLabelPadding = this.options.xLabelPadding;
 47 |   var yLabelPadding = 3;
 48 |   var xPadding = this.options.xPadding;
 49 |   var yPadding = 11;
 50 |   var c = this.ctx;
 51 |   var labels = data[0].x;
 52 | 
 53 |   function addLegend() {
 54 |     if (!self.options.showLegend) return;
 55 |     if (self.legend) self.remove(self.legend);
 56 |     var legendWidth = self.options.legend.width || 15;
 57 |     self.legend = blessed.box({
 58 |       height: data.length+2,
 59 |       top: 1,
 60 |       width: legendWidth,
 61 |       left: self.width-legendWidth-3,
 62 |       content: '',
 63 |       fg: 'green',
 64 |       tags: true,
 65 |       border: {
 66 |         type: 'line',
 67 |         fg: 'black'
 68 |       },
 69 |       style: {
 70 |         fg: 'blue',
 71 |       },
 72 |       screen: self.screen
 73 |     });
 74 | 
 75 |     var legandText = '';
 76 |     var maxChars = legendWidth-2;
 77 |     for (let i=0; i<data.length; i++) {
 78 |       var style = data[i].style || {};
 79 |       var color = utils.getColorCode(style.line || self.options.style.line);
 80 |       legandText += '{'+color+'-fg}'+ data[i].title.substring(0, maxChars)+'{/'+color+'-fg}\r\n';
 81 |     }
 82 |     self.legend.setContent(legandText);
 83 |     self.append(self.legend);
 84 |   }
 85 | 
 86 |   //iteratee for lodash _.max
 87 |   function getMaxY() {
 88 |     if (self.options.maxY) {
 89 |       return self.options.maxY;
 90 |     }
 91 | 
 92 |     var max = -Infinity;
 93 | 
 94 |     for(let i = 0; i < data.length; i++) {
 95 |       if (data[i].y.length) {
 96 |         var current = _.max(data[i].y, parseFloat);
 97 |         if (current > max) {
 98 |           max = current;
 99 |         }
100 |       }
101 |     }
102 | 
103 |     return max + (max - self.options.minY) * 0.2;
104 |   }
105 | 
106 |   function formatYLabel(value, max, min, numLabels, wholeNumbersOnly, abbreviate) {
107 |     var fixed = (((max - min) / numLabels) < 1 && value!=0 && !wholeNumbersOnly) ? 2 : 0;
108 |     var res = value.toFixed(fixed);
109 |     return abbreviate?utils.abbreviateNumber(res):res;
110 |   }
111 | 
112 |   function getMaxXLabelPadding(numLabels, wholeNumbersOnly, abbreviate, min) {
113 |     var max = getMaxY();
114 | 
115 |     return formatYLabel(max, max, min, numLabels, wholeNumbersOnly, abbreviate).length * 2;
116 |   }
117 | 
118 |   var maxPadding = getMaxXLabelPadding(this.options.numYLabels, this.options.wholeNumbersOnly, this.options.abbreviate, this.options.minY);
119 |   if (xLabelPadding < maxPadding) {
120 |     xLabelPadding = maxPadding;
121 |   }
122 | 
123 |   if ((xPadding - xLabelPadding) < 0) {
124 |     xPadding = xLabelPadding;
125 |   }
126 | 
127 |   function getMaxX() {
128 |     var maxLength = 0;
129 | 
130 |     for(var i = 0; i < labels.length; i++) {
131 |       if(labels[i] === undefined) {
132 |         // console.log("label[" + i + "] is undefined");
133 |       } else if(labels[i].length > maxLength) {
134 |         maxLength = labels[i].length;
135 |       }
136 |     }
137 | 
138 |     return maxLength;
139 |   }
140 | 
141 |   function getXPixel(val) {
142 |     return ((self.canvasSize.width - xPadding) / labels.length) * val + (xPadding * 1.0) + 2;
143 |   }
144 | 
145 |   function getYPixel(val, minY) {
146 |     var res = self.canvasSize.height - yPadding - (((self.canvasSize.height - yPadding) / (getMaxY()-minY)) * (val-minY));
147 |     res-=2; //to separate the baseline and the data line to separate chars so canvas will show separate colors
148 |     return res;
149 |   }
150 | 
151 |   // Draw the line graph
152 |   function drawLine(values, style, minY) {
153 |     style = style || {};
154 |     var color = self.options.style.line;
155 |     c.strokeStyle = style.line || color;
156 | 
157 |     c.moveTo(0, 0);
158 |     c.beginPath();
159 |     c.lineTo(getXPixel(0), getYPixel(values[0], minY));
160 | 
161 |     for(var k = 1; k < values.length; k++) {
162 |       c.lineTo(getXPixel(k), getYPixel(values[k], minY));
163 |     }
164 | 
165 |     c.stroke();
166 |   }
167 | 
168 |   addLegend();
169 | 
170 |   c.fillStyle = this.options.style.text;
171 | 
172 |   c.clearRect(0, 0, this.canvasSize.width, this.canvasSize.height);
173 | 
174 | 
175 |   var yLabelIncrement = (getMaxY()-this.options.minY)/this.options.numYLabels;
176 |   if (this.options.wholeNumbersOnly) yLabelIncrement = Math.floor(yLabelIncrement);
177 |   //if (getMaxY()>=10) {
178 |   //  yLabelIncrement = yLabelIncrement + (10 - yLabelIncrement % 10)
179 |   //}
180 | 
181 |   //yLabelIncrement = Math.max(yLabelIncrement, 1) // should not be zero
182 | 
183 |   if (yLabelIncrement==0) yLabelIncrement = 1;
184 | 
185 |   // Draw the Y value texts
186 |   var maxY = getMaxY();
187 |   for(var i = this.options.minY; i < maxY; i += yLabelIncrement) {
188 |     c.fillText(formatYLabel(i, maxY, this.options.minY, this.options.numYLabels, this.options.wholeNumbersOnly, this.options.abbreviate), xPadding - xLabelPadding, getYPixel(i, this.options.minY));
189 |   }
190 | 
191 |   for (var h=0; h<data.length; h++) {
192 |     drawLine(data[h].y, data[h].style, this.options.minY);
193 |   }
194 | 
195 | 
196 |   c.strokeStyle = this.options.style.baseline;
197 | 
198 |   // Draw the axises
199 |   c.beginPath();
200 | 
201 |   c.lineTo(xPadding, 0);
202 |   c.lineTo(xPadding, this.canvasSize.height - yPadding);
203 |   c.lineTo(this.canvasSize.width, this.canvasSize.height - yPadding);
204 | 
205 |   c.stroke();
206 | 
207 |   // Draw the X value texts
208 |   var charsAvailable = (this.canvasSize.width - xPadding) / 2;
209 |   var maxLabelsPossible = charsAvailable / (getMaxX() + 2);
210 |   var pointsPerMaxLabel = Math.ceil(data[0].y.length / maxLabelsPossible);
211 |   var showNthLabel = this.options.showNthLabel;
212 |   if (showNthLabel < pointsPerMaxLabel) {
213 |     showNthLabel = pointsPerMaxLabel;
214 |   }
215 | 
216 |   for(let i = 0; i < labels.length; i += showNthLabel) {
217 |     if((getXPixel(i) + (labels[i].length * 2)) <= this.canvasSize.width) {
218 |       c.fillText(labels[i], getXPixel(i), this.canvasSize.height - yPadding + yLabelPadding);
219 |     }
220 |   }
221 | 
222 | };
223 | 
224 | Line.prototype.getOptionsPrototype = function() {
225 |   return { width: 80
226 |     , height: 30
227 |     , left: 15
228 |     , top: 12
229 |     , xPadding: 5
230 |     , label: 'Title'
231 |     , showLegend: true
232 |     , legend: {width: 12}
233 |     , data: [ { title: 'us-east',
234 |       x: ['t1', 't2', 't3', 't4'],
235 |       y: [5, 1, 7, 5],
236 |       style: {
237 |         line: 'red'
238 |       }
239 |     }
240 |     , { title: 'us-west',
241 |       x: ['t1', 't2', 't3', 't4'],
242 |       y: [2, 4, 9, 8],
243 |       style: {line: 'yellow'}
244 |     }
245 |     , {title: 'eu-north-with-some-long-string',
246 |       x: ['t1', 't2', 't3', 't4'],
247 |       y: [22, 7, 12, 1],
248 |       style: {line: 'blue'}
249 |     }]
250 | 
251 |   };
252 | };
253 | 
254 | module.exports = Line;
255 | 


--------------------------------------------------------------------------------
/lib/widget/charts/stacked-bar.js:
--------------------------------------------------------------------------------
  1 | 'use strict';
  2 | var blessed = require('blessed')
  3 |   , Node = blessed.Node
  4 |   , Canvas = require('../canvas')
  5 |   , utils = require('../../utils.js');
  6 | 
  7 | function StackedBar(options) {
  8 |   if (!(this instanceof Node)) {
  9 |     return new StackedBar(options);
 10 |   }
 11 | 
 12 |   var self = this;
 13 |   Canvas.call(this, options, require('ansi-term'));
 14 | 
 15 |   this.options.barWidth = this.options.barWidth || 6;
 16 |   this.options.barSpacing = this.options.barSpacing || 9;
 17 | 
 18 |   if ((this.options.barSpacing - this.options.barWidth) < 3) {
 19 |     this.options.barSpacing = this.options.barWidth + 3;
 20 |   }
 21 | 
 22 |   this.options.xOffset = this.options.xOffset==null? 5 : this.options.xOffset;
 23 |   if (this.options.showText === false)
 24 |     this.options.showText = false;
 25 |   else
 26 |     this.options.showText = true;
 27 | 
 28 |   this.options.legend = this.options.legend || {};
 29 |   if (this.options.showLegend === false)
 30 |     this.options.showLegend = false;
 31 |   else
 32 |     this.options.showLegend = true;
 33 | 
 34 |   this.on('attach', function() {
 35 |     if (self.options.data) {
 36 |       self.setData(self.options.data);
 37 |     }
 38 |   });
 39 | }
 40 | 
 41 | StackedBar.prototype = Object.create(Canvas.prototype);
 42 | 
 43 | StackedBar.prototype.calcSize = function() {
 44 |   this.canvasSize = {width: this.width-2, height: this.height};
 45 | };
 46 | 
 47 | StackedBar.prototype.getSummedBars = function(bars) {
 48 |   var res = [];
 49 |   bars.forEach(function(stackedValues) {
 50 |     var sum = stackedValues.reduce(function(a,b) {
 51 |       return a + b;
 52 |     } , 0);
 53 |     res.push(sum);
 54 |   });
 55 |   return res;
 56 | };
 57 | 
 58 | StackedBar.prototype.setData = function(bars) {
 59 | 
 60 |   if (!this.ctx) {
 61 |     throw 'error: canvas context does not exist. setData() for bar charts must be called after the chart has been added to the screen via screen.append()';
 62 |   }
 63 | 
 64 |   this.clear();
 65 | 
 66 |   var summedBars = this.getSummedBars(bars.data);
 67 |   var maxBarValue = Math.max.apply(Math, summedBars);
 68 |   if (this.options.maxValue)
 69 |     maxBarValue = Math.max(maxBarValue, this.options.maxValue);
 70 |   var x = this.options.xOffset;
 71 |   for (var i = 0; i < bars.data.length; i++) {
 72 |     this.renderBar(x, bars.data[i], summedBars[i], maxBarValue, bars.barCategory[i]);
 73 |     x += this.options.barSpacing;
 74 |   }
 75 | 
 76 |   this.addLegend(bars, x);
 77 | };
 78 | 
 79 | StackedBar.prototype.renderBar = function(x, bar, curBarSummedValue, maxBarValue, category) {
 80 | /*
 81 |   var c = this.ctx
 82 |   c.strokeStyle = 'red';
 83 |   c.fillRect(0,7,4,0)
 84 |   c.strokeStyle = 'blue';
 85 |   c.fillRect(0,4,4,1)
 86 |   c.strokeStyle = 'green';
 87 |   c.fillRect(5,7,4,2)
 88 |   return
 89 | */
 90 |   //first line is for label
 91 |   const BUFFER_FROM_TOP = 2;
 92 |   const BUFFER_FROM_BOTTOM = (this.options.border ? 2 : 0) + (this.options.showText ? 1 : 0);
 93 | 
 94 |   var c = this.ctx;
 95 |   c.strokeStyle = 'normal';
 96 |   c.fillStyle = 'white';
 97 |   if (this.options.labelColor)
 98 |     c.fillStyle = this.options.labelColor;
 99 |   if (this.options.showText) {
100 |     c.fillText(category, x + 1, this.canvasSize.height - BUFFER_FROM_BOTTOM);
101 |   }
102 | 
103 |   if (curBarSummedValue < 0) return;
104 |   var maxBarHeight = this.canvasSize.height - BUFFER_FROM_TOP - BUFFER_FROM_BOTTOM;
105 |   var currentBarHeight = Math.round(maxBarHeight * (curBarSummedValue / maxBarValue));
106 |   //start painting from bottom of bar, section by section
107 |   var y = maxBarHeight + BUFFER_FROM_TOP;
108 |   var availableBarHeight = currentBarHeight;
109 |   for (var i=0; i < bar.length; i++) {
110 |     var currStackHeight = this.renderBarSection(
111 |       x,
112 |       y,
113 |       bar[i],
114 |       curBarSummedValue,
115 |       currentBarHeight,
116 |       availableBarHeight,
117 |       this.options.barBgColor[i]);
118 |     y -= currStackHeight;
119 |     availableBarHeight -= currStackHeight;
120 |   }
121 | };
122 | 
123 | StackedBar.prototype.renderBarSection = function(
124 |   x,
125 |   y,
126 |   data,
127 |   curBarSummedValue,
128 |   currentBarHeight,
129 |   availableBarHeight,
130 |   bg) {
131 |   var c = this.ctx;
132 | 
133 |   var currStackHeight = currentBarHeight <= 0?
134 |     0 :
135 |     Math.min(
136 |       availableBarHeight, //round() can make total stacks excceed curr bar height so we limit it
137 |       Math.round(currentBarHeight * (data / curBarSummedValue))
138 |     );
139 |   c.strokeStyle = bg;
140 | 
141 |   if (currStackHeight>0) {
142 |     var calcY = y - currStackHeight;
143 |     /*fillRect starts from the point bottom of start point so we compensate*/
144 |     var calcHeight = Math.max(0, currStackHeight-1);
145 |     c.fillRect(
146 |       x,
147 |       calcY,
148 |       this.options.barWidth,
149 |       calcHeight
150 |     );
151 | 
152 |     c.fillStyle = 'white';
153 |     if (this.options.barFgColor)
154 |       c.fillStyle = this.options.barFgColor;
155 |     if (this.options.showText) {
156 |       var str = utils.abbreviateNumber(data.toString());
157 |       c.fillText(
158 |         str,
159 |         Math.floor(x + this.options.barWidth/2 + str.length/2),
160 |         calcY + Math.round(calcHeight/2));
161 |     }
162 |   }
163 | 
164 |   return currStackHeight;
165 | };
166 | 
167 | StackedBar.prototype.getOptionsPrototype = function() {
168 |   return  {  barWidth: 1
169 |     ,  barSpacing: 1
170 |     ,  xOffset: 1
171 |     ,  maxValue: 1
172 |     ,  barBgColor: 's'
173 |     ,  data: { barCategory: ['s']
174 |       , stackedCategory: ['s']
175 |       , data: [ [ 1] ]
176 |     }
177 |   };
178 | };
179 | 
180 | 
181 | 
182 | StackedBar.prototype.addLegend = function(bars, x) {
183 |   var self = this;
184 |   if (!self.options.showLegend) return;
185 |   if (self.legend) self.remove(self.legend);
186 |   var legendWidth = self.options.legend.width || 15;
187 |   self.legend = blessed.box({
188 |     height: bars.stackedCategory.length+2,
189 |     top: 1,
190 |     width: legendWidth,
191 |     left: x,
192 |     content: '',
193 |     fg: 'green',
194 |     tags: true,
195 |     border: {
196 |       type: 'line',
197 |       fg: 'black'
198 |     },
199 |     style: {
200 |       fg: 'blue',
201 |     },
202 |     screen: self.screen
203 |   });
204 | 
205 |   var legandText = '';
206 |   var maxChars = legendWidth-2;
207 |   for (var i=0; i<bars.stackedCategory.length; i++) {
208 |     var color = utils.getColorCode(self.options.barBgColor[i]);
209 |     legandText += '{'+color+'-fg}'+ bars.stackedCategory[i].substring(0, maxChars)+'{/'+color+'-fg}\r\n';
210 |   }
211 |   self.legend.setContent(legandText);
212 |   self.append(self.legend);
213 | };
214 | 
215 | StackedBar.prototype.type = 'bar';
216 | 
217 | module.exports = StackedBar;
218 | 


--------------------------------------------------------------------------------
/lib/widget/donut.js:
--------------------------------------------------------------------------------
  1 | 'use strict';
  2 | var blessed = require('blessed')
  3 |   , Node = blessed.Node
  4 |   , Canvas = require('./canvas');
  5 | 
  6 | function Donut(options) {
  7 |   if (!(this instanceof Node)) {
  8 |     return new Donut(options);
  9 |   }
 10 | 
 11 |   options = options || {};
 12 |   this.options = options;
 13 |   this.options.stroke = options.stroke || 'magenta';
 14 |   this.options.fill = options.fill || 'white';
 15 |   this.options.radius = options.radius || 14;
 16 |   this.options.arcWidth = options.arcWidth || 4;
 17 |   this.options.spacing = options.spacing || 2;
 18 |   this.options.yPadding = options.yPadding || 2;
 19 |   this.options.remainColor = options.remainColor || 'black';
 20 |   this.options.data = options.data || [];
 21 | 
 22 |   Canvas.call(this, options);
 23 | 
 24 |   var self = this;
 25 |   this.on('attach', function() {
 26 |     this.setData(self.options.data);
 27 |   });
 28 | }
 29 | 
 30 | Donut.prototype = Object.create(Canvas.prototype);
 31 | 
 32 | Donut.prototype.calcSize = function() {
 33 |   this.canvasSize = {width: Math.round(this.width*2-5), height: this.height*4-12};
 34 |   if (this.canvasSize.width % 2 == 1)
 35 |     this.canvasSize.width--;
 36 |   if (this.canvasSize.height % 4 != 1)
 37 |     this.canvasSize.height += (this.canvasSize.height % 4);
 38 | };
 39 | 
 40 | Donut.prototype.type = 'donut';
 41 | 
 42 | var cos = Math.cos;
 43 | var sin = Math.sin;
 44 | var pi = 3.141592635;
 45 | Donut.prototype.setData = function(data){
 46 |   this.update(data);
 47 | };
 48 | Donut.prototype.update = function(data) {
 49 | 
 50 |   if (!this.ctx) {
 51 |     throw 'error: canvas context does not exist. setData() for line charts must be called after the chart has been added to the screen via screen.append()';
 52 |   }
 53 | 
 54 |   var c = this.ctx;
 55 |   c.save();
 56 |   c.translate(0,-this.options.yPadding);
 57 | 
 58 |   c.strokeStyle = this.options.stroke;
 59 |   c.fillStyle = this.options.fill;
 60 | 
 61 |   c.clearRect(0, 0, this.canvasSize.width, this.canvasSize.height);
 62 | 
 63 |   var cheight = this.canvasSize.height;
 64 |   var cwidth = this.canvasSize.width;
 65 | 
 66 |   function makeRound(percent, radius, width, cx, cy, color){
 67 |     var s = 0;
 68 |     var points = 370;
 69 |     c.strokeStyle = color || 'green';
 70 |     while(s<radius){
 71 |       if (s < (radius - width)) {
 72 |         s++;
 73 |         continue;
 74 |       }
 75 |       var slice = 2 * pi / points;
 76 |       c.beginPath();
 77 |       var p = parseFloat(percent*360);
 78 |       for(var i = 0;i<=points;i++){
 79 |         if (i>p) continue;
 80 |         var si = i-90;
 81 |         var a = slice * si;
 82 |         c.lineTo(Math.round(cx+s*cos(a)), Math.round(cy+s*sin(a)));
 83 |       }
 84 |       c.stroke();
 85 |       c.closePath();
 86 |       s++;
 87 |     }
 88 |   }
 89 | 
 90 |   var donuts = data.length;
 91 |   var radius = this.options.radius;
 92 |   var width = this.options.arcWidth;
 93 |   var remainColor = this.options.remainColor;
 94 | 
 95 |   var middle = cheight / 2;
 96 |   var spacing = (cwidth - (donuts * radius * 2)) / (donuts + 1);
 97 | 
 98 |   function drawDonut(label, percent, radius, width, cxx, middle, color, percentAltNumber){
 99 |     makeRound(100, radius, width, cxx, middle, remainColor );
100 |     makeRound(percent, radius, width, cxx, middle, color);
101 |     var ptext = percentAltNumber ? percentAltNumber.toFixed(0) : parseFloat(percent*100).toFixed(0) + '%';
102 |     c.fillText(ptext, cxx - Math.round(parseFloat((c.measureText(ptext).width)/2)) + 3, middle);
103 |     c.fillText(label, cxx - Math.round(parseFloat((c.measureText(label).width)/2)) + 3, (middle + radius) + 5);
104 |   }
105 | 
106 |   function makeDonut(stat, which){
107 |     var left = radius + (spacing * which) + (radius * 2 * (which - 1));
108 |     var percent = stat.percent;
109 |     if (percent > 1.001){
110 |       percent = parseFloat(percent / 100).toFixed(2);
111 |     }
112 |     var label = stat.label;
113 |     var percentAltNumber = stat.percentAltNumber;
114 |     var color = stat.color || 'green';
115 |     var cxx = left;
116 |     drawDonut(label, percent, radius, width, cxx, middle, color, percentAltNumber);
117 |   }
118 |   function makeDonuts(stats){
119 |     for(var l = 0; l<=stats.length-1;l++){
120 |       makeDonut(stats[l], l+1);
121 |     }
122 |   }
123 | 
124 |   if (data.length){
125 |     makeDonuts(data);
126 |   }
127 | 
128 |   this.currentData = data;
129 | 
130 |   c.strokeStyle = 'magenta';
131 | 
132 |   c.restore();
133 |   return;
134 | };
135 | 
136 | Donut.prototype.getOptionsPrototype = function() {
137 |   return {
138 |     spacing: 1,
139 |     yPadding: 1,
140 |     radius: 1,
141 |     arcWidth: 1,
142 |     data: [ { color: 'red', percent: '50', label: 'a'}
143 |       , { color: 'blue', percent: '20', label: 'b'}
144 |       , { color: 'yellow', percent: '80', label: 'c'}
145 |     ]
146 |   };
147 | };
148 | 
149 | module.exports = Donut;
150 | 


--------------------------------------------------------------------------------
/lib/widget/gauge-list.js:
--------------------------------------------------------------------------------
  1 | 'use strict';
  2 | var blessed = require('blessed')
  3 |   , Node = blessed.Node
  4 |   , Canvas = require('./canvas');
  5 | 
  6 | function GaugeList(options) {
  7 |   if (!(this instanceof Node)) {
  8 |     return new GaugeList(options);
  9 |   }
 10 | 
 11 |   var self = this;
 12 | 
 13 |   options = options || {};
 14 |   self.options = options;
 15 |   self.options.stroke = options.stroke || 'magenta';
 16 |   self.options.fill = options.fill || 'white';
 17 |   self.options.data = options.data || [];
 18 |   self.options.showLabel = options.showLabel !== false;
 19 |   self.options.gaugeSpacing = options.gaugeSpacing || 0;
 20 |   self.options.gaugeHeight = options.gaugeHeight || 1;
 21 | 
 22 |   Canvas.call(this, options, require('ansi-term'));
 23 | 
 24 |   this.on('attach', function() {
 25 |     var gauges = this.gauges = self.options.gauges;
 26 |     this.setGauges(gauges);
 27 |   });
 28 | 
 29 | }
 30 | 
 31 | GaugeList.prototype = Object.create(Canvas.prototype);
 32 | 
 33 | GaugeList.prototype.calcSize = function() {
 34 |   this.canvasSize = {width: this.width-2, height: this.height};
 35 | };
 36 | 
 37 | GaugeList.prototype.type = 'gauge';
 38 | 
 39 | GaugeList.prototype.setData = function() {
 40 | };
 41 | 
 42 | GaugeList.prototype.setGauges = function(gauges) {
 43 | 
 44 |   if (!this.ctx) {
 45 |     throw 'error: canvas context does not exist. setData() for gauges must be called after the gauge has been added to the screen via screen.append()';
 46 |   }
 47 | 
 48 |   var c = this.ctx;
 49 |   c.clearRect(0, 0, this.canvasSize.width, this.canvasSize.height);
 50 | 
 51 |   for (var i=0; i<gauges.length; i++) {
 52 |     this.setSingleGauge(gauges[i], i);
 53 |   }
 54 | 
 55 | };
 56 | 
 57 | GaugeList.prototype.setSingleGauge = function(gauge, offset) {
 58 | 
 59 |   var colors = ['green','magenta','cyan','red','blue'];
 60 |   var stack = gauge.stack;
 61 | 
 62 |   var c = this.ctx;
 63 |   var leftStart = 3;
 64 |   var textLeft = 5;
 65 | 
 66 |   c.strokeStyle='normal';
 67 |   c.fillStyle='white';
 68 |   c.fillText(offset.toString(), 0, offset*(this.options.gaugeHeight+this.options.gaugeSpacing));
 69 | 
 70 |   for (var i = 0; i < stack.length; i++) {
 71 |     var currentStack = stack[i];
 72 | 
 73 |     var percent;
 74 |     if (typeof(currentStack) == typeof({})){
 75 |       percent = currentStack.percent;
 76 |     } else {
 77 |       percent = currentStack;
 78 |     }
 79 | 
 80 |     c.strokeStyle = currentStack.stroke || colors[(i%colors.length)]; // use specified or choose from the array of colors
 81 |     c.fillStyle = this.options.fill;//'white'
 82 | 
 83 |     textLeft = 5;
 84 | 
 85 |     var width = percent/100*(this.canvasSize.width-5);
 86 | 
 87 |     c.fillRect(leftStart, offset*(this.options.gaugeHeight+this.options.gaugeSpacing), width, this.options.gaugeHeight-1);
 88 | 
 89 |     textLeft = (width / 2) - 1;
 90 |     // if (textLeft)
 91 |     var textX = leftStart+textLeft;
 92 | 
 93 |     if ((leftStart+width)<textX) {
 94 |       c.strokeStyle = 'normal';
 95 |     }
 96 |     if (gauge.showLabel) c.fillText(percent+'%', textX, 3);
 97 | 
 98 |     leftStart += width;
 99 |   }
100 | };
101 | 
102 | GaugeList.prototype.getOptionsPrototype = function() {
103 |   return {percent: 10};
104 | };
105 | 
106 | module.exports = GaugeList;
107 | 


--------------------------------------------------------------------------------
/lib/widget/gauge.js:
--------------------------------------------------------------------------------
  1 | 'use strict';
  2 | var blessed = require('blessed')
  3 |   , Node = blessed.Node
  4 |   , Canvas = require('./canvas');
  5 | 
  6 | function Gauge(options) {
  7 |   if (!(this instanceof Node)) {
  8 |     return new Gauge(options);
  9 |   }
 10 | 
 11 |   var self = this;
 12 | 
 13 |   options = options || {};
 14 |   self.options = options;
 15 |   self.options.stroke = options.stroke || 'magenta';
 16 |   self.options.fill = options.fill || 'white';
 17 |   self.options.data = options.data || [];
 18 |   self.options.showLabel = options.showLabel !== false;
 19 | 
 20 |   Canvas.call(this, options, require('ansi-term'));
 21 | 
 22 |   this.on('attach', function() {
 23 |     if (self.options.stack) {
 24 |       var stack = this.stack = self.options.stack;
 25 |       this.setStack(stack);
 26 |     } else {
 27 |       var percent = this.percent = self.options.percent || 0;
 28 |       this.setData(percent);
 29 |     }
 30 |   });
 31 | }
 32 | 
 33 | Gauge.prototype = Object.create(Canvas.prototype);
 34 | 
 35 | Gauge.prototype.calcSize = function() {
 36 |   this.canvasSize = {width: this.width-2, height: this.height};
 37 | };
 38 | 
 39 | Gauge.prototype.type = 'gauge';
 40 | 
 41 | Gauge.prototype.setData = function(data){
 42 |   if (typeof(data) == typeof([]) && data.length > 0){
 43 |     this.setStack(data);
 44 |   } else if(typeof(data) == typeof(1)) {
 45 |     this.setPercent(data);
 46 |   }
 47 | };
 48 | 
 49 | Gauge.prototype.setPercent = function(percent) {
 50 | 
 51 |   if (!this.ctx) {
 52 |     throw 'error: canvas context does not exist. setData() for gauges must be called after the gauge has been added to the screen via screen.append()';
 53 |   }
 54 | 
 55 |   var c = this.ctx;
 56 | 
 57 |   c.strokeStyle = this.options.stroke;//'magenta'
 58 |   c.fillStyle = this.options.fill;//'white'
 59 | 
 60 |   c.clearRect(0, 0, this.canvasSize.width, this.canvasSize.height);
 61 |   if (percent < 1.001){
 62 |     percent = percent * 100;
 63 |   }
 64 |   var width = percent/100*(this.canvasSize.width-3);
 65 |   c.fillRect(1, 2, width, 2);
 66 | 
 67 |   var textX = 7;
 68 |   if (width<textX) {
 69 |     c.strokeStyle = 'normal';
 70 |   }
 71 | 
 72 |   if (this.options.showLabel) c.fillText(Math.round(percent)+'%', textX, 3);
 73 | };
 74 | 
 75 | Gauge.prototype.setStack = function(stack) {
 76 |   var colors = ['green','magenta','cyan','red','blue'];
 77 | 
 78 |   if (!this.ctx) {
 79 |     throw 'error: canvas context does not exist. setData() for gauges must be called after the gauge has been added to the screen via screen.append()';
 80 |   }
 81 | 
 82 |   var c = this.ctx;
 83 |   var leftStart = 1;
 84 |   var textLeft = 5;
 85 |   c.clearRect(0, 0, this.canvasSize.width, this.canvasSize.height);
 86 | 
 87 |   for (var i = 0; i < stack.length; i++) {
 88 |     var currentStack = stack[i];
 89 | 
 90 |     let percent;
 91 |     if (typeof(currentStack) == typeof({}))
 92 |       percent = currentStack.percent;
 93 |     else
 94 |       percent = currentStack;
 95 | 
 96 |     c.strokeStyle = currentStack.stroke || colors[(i%colors.length)]; // use specified or choose from the array of colors
 97 |     c.fillStyle = this.options.fill;//'white'
 98 | 
 99 |     textLeft = 5;
100 |     if (percent < 1.001){
101 |       percent = percent * 100;
102 |     }
103 |     var width = percent/100*(this.canvasSize.width-3);
104 | 
105 |     c.fillRect(leftStart, 2, width, 2);
106 | 
107 |     textLeft = (width / 2) - 1;
108 |     // if (textLeft)
109 |     var textX = leftStart+textLeft;
110 | 
111 |     if ((leftStart+width)<textX) {
112 |       c.strokeStyle = 'normal';
113 |     }
114 |     if (this.options.showLabel) c.fillText(percent+'%', textX, 3);
115 | 
116 |     leftStart += width;
117 |   }
118 | };
119 | 
120 | Gauge.prototype.getOptionsPrototype = function() {
121 |   return {percent: 10};
122 | };
123 | 
124 | 
125 | module.exports = Gauge;
126 | 


--------------------------------------------------------------------------------
/lib/widget/lcd.js:
--------------------------------------------------------------------------------
  1 | 'use strict';
  2 | var blessed = require('blessed')
  3 |   , Node = blessed.Node
  4 |   , Canvas = require('./canvas');
  5 | 
  6 | function LCD(options) {
  7 |   if (!(this instanceof Node)) {
  8 |     return new LCD(options);
  9 |   }
 10 |   var self = this;
 11 | 
 12 |   options = options || {};
 13 |   self.options = options;
 14 | 
 15 |   //these options need to be modified epending on the resulting positioning/size
 16 |   self.options.segmentWidth = options.segmentWidth || 0.06; // how wide are the segments in % so 50% = 0.5
 17 |   self.options.segmentInterval = options.segmentInterval || 0.11; // spacing between the segments in % so 50% = 0.5
 18 |   self.options.strokeWidth = options.strokeWidth || 0.11; // spacing between the segments in % so 50% = 0.5
 19 | 
 20 |   //default display settings
 21 |   self.options.elements = options.elements || 3; // how many elements in the display. or how many characters can be displayed.
 22 |   self.options.display = options.display || 321; // what should be displayed before anything is set
 23 |   self.options.elementSpacing = options.spacing || 4; // spacing between each element
 24 |   self.options.elementPadding = options.padding || 2; // how far away from the edges to put the elements
 25 | 
 26 |   //coloring
 27 |   self.options.color = options.color || 'white';
 28 | 
 29 |   Canvas.call(this, options);
 30 | 
 31 |   this.segment16 = null;
 32 | 
 33 |   this.on('attach', function() {
 34 |     var display = self.options.display || 1234;
 35 |     if (!this.segment16)
 36 |       this.segment16 = new SixteenSegment(this.options.elements, this.ctx, this.canvasSize.width, this.canvasSize.height, 0, 0, this.options);
 37 | 
 38 |     this.setDisplay(display);
 39 |   });
 40 | }
 41 | 
 42 | LCD.prototype = Object.create(Canvas.prototype);
 43 | 
 44 | LCD.prototype.calcSize = function() {
 45 |   this.canvasSize = {width: this.width*2-8, height: (this.height*4)-12};
 46 | };
 47 | 
 48 | LCD.prototype.type = 'lcd';
 49 | LCD.prototype.increaseWidth = function(){
 50 |   if (this.segment16){
 51 |     this.segment16.SegmentWidth+=0.01;
 52 |   }
 53 | };
 54 | LCD.prototype.decreaseWidth = function(){
 55 |   if (this.segment16){
 56 |     this.segment16.SegmentWidth-=0.01;
 57 |   }
 58 | };
 59 | LCD.prototype.increaseInterval = function(){
 60 |   if (this.segment16){
 61 |     this.segment16.SegmentInterval+=0.01;
 62 |   }
 63 | };
 64 | LCD.prototype.decreaseInterval = function(){
 65 |   if (this.segment16){
 66 |     this.segment16.SegmentInterval-=0.01;
 67 |   }
 68 | };
 69 | LCD.prototype.increaseStroke = function(){
 70 |   if (this.segment16){
 71 |     this.segment16.StrokeWidth+=0.05;
 72 |   }
 73 | };
 74 | LCD.prototype.decreaseStroke = function(){
 75 |   if (this.segment16){
 76 |     this.segment16.StrokeWidth-=0.05;
 77 |   }
 78 | };
 79 | LCD.prototype.setOptions = function(options){
 80 |   if (this.segment16){
 81 |     this.segment16.setOptions(options);
 82 |   }
 83 | };
 84 | 
 85 | LCD.prototype.setData = function(data){
 86 |   this.setDisplay(data.toString());
 87 | };
 88 | 
 89 | LCD.prototype.getOptionsPrototype = function() {
 90 |   return {
 91 |     label: 'LCD Test',
 92 |     segmentWidth: 0.06,
 93 |     segmentInterval: 0.11,
 94 |     strokeWidth: 0.1,
 95 |     elements: 5,
 96 |     display: 3210,
 97 |     elementSpacing: 4,
 98 |     elementPadding: 2
 99 |   };
100 | };
101 | 
102 | LCD.prototype.setDisplay = function(display) {
103 | 
104 |   if (!this.ctx) {
105 |     throw 'error: canvas context does not exist. setData() for line charts must be called after the chart has been added to the screen via screen.append()';
106 |   }
107 | 
108 |   this.ctx.clearRect(0, 0, this.canvasSize.width, this.canvasSize.height);
109 | 
110 |   this.segment16.DisplayText(display);
111 | };
112 | 
113 | function ElementArray(count) {
114 |   this.SetCount = SetCount;
115 |   this.SetText = SetText;
116 |   this.SetElementValue = SetElementValue;
117 |   this.NullMask = 0x10;
118 |   this.Elements = [];
119 |   this.SetCount(count || 0);
120 | 
121 |   function SetCount(count) {
122 |     var c = parseInt(count, 10);
123 |     if (isNaN(c)) {
124 |       throw 'Invalid element count: ' + count;
125 |     }
126 |     this.Elements = [c];
127 |     for (var i = 0; i < c; i++) {
128 |       this.Elements[i] = 0;
129 |     }
130 |   }
131 | 
132 |   function SetText(value, charMaps) {
133 |     // Get the string of the value passed in
134 |     if (value === null) {
135 |       value = '';
136 |     }
137 |     value = value.toString();
138 | 
139 |     // Clear the elements
140 |     for (var i = 0; i < this.Elements.length; i++) {
141 |       this.SetElementValue(i, 0);
142 |     }
143 |     if (value.length === 0) {
144 |       return;
145 |     }
146 |     // Set the bitmask to dispay the proper character for each element
147 |     for (var e = 0; e < this.Elements.length && e < value.length; e++){
148 |       var c = value[e];
149 |       var mask = charMaps[c];
150 |       // Use blank of there is no bitmask for this character
151 |       if (mask === null || mask === undefined) {
152 |         mask = this.NullMask;
153 |       }
154 |       this.SetElementValue(e, mask);
155 |     }
156 |   }
157 |   function SetElementValue(i, value) {
158 |     if (i >= 0 && i < this.Elements.length){
159 |       this.Elements[i] = parseInt(value, 10);
160 |     }
161 |   }
162 | }
163 | 
164 | //thx to https://github.com/Enderer/sixteensegment!!!
165 | //although it needed HEAVY rework since it was already somewhat busted ;-(
166 | function SixteenSegment(count, canvas, width, height, x, y, options){
167 |   this.ElementArray = new ElementArray(count);
168 | 
169 |   this.SegmentWidth = options.segmentWidth;//(this.ElementWidth * 0.0015) * 5 //0.1;           // Width of segments (% of Element Width)
170 |   this.SegmentInterval = options.segmentInterval;//(this.ElementWidth * 0.0015) * 10 // 0.20;        // Spacing between segments (% of Element Width)
171 |   this.BevelWidth = 0.01;             // Size of corner bevel (% of Element Width)
172 |   this.SideBevelEnabled = true;      // Should the sides be beveled
173 |   this.StrokeLight = options.color;       // Color of an on segment outline
174 | 
175 |   this.StrokeWidth = options.strokeWidth;               // Width of segment outline
176 |   this.Padding = options.elementPadding;                   // Padding around the display
177 |   this.Spacing = options.elementSpacing;                   // Spacing between elements
178 | 
179 |   this.ElementWidth = (width - (this.Spacing*count))/count;
180 |   this.ElementHeight = height - (this.Padding*2);
181 | 
182 |   // console.error("w %s h %s", this.ElementWidth, this.ElementHeight);
183 | 
184 |   this.FillLight = 'red';           // Color of an on segment
185 |   this.FillDark = 'cyan';             // Color of an off segment
186 |   this.StrokeDark = 'black';          // Color of an off segment outline
187 | 
188 |   this.X = 0;
189 |   this.Y = 0;
190 | 
191 |   this.ElementCount = count;
192 | 
193 |   this.CalcElementDimensions = CalcElementDimensions;
194 |   this.FlipVertical = FlipVertical;
195 |   this.FlipHorizontal = FlipHorizontal;
196 |   this.CalcPoints = CalcPoints;
197 |   this.DisplayText = DisplayText;
198 |   this.Draw = Draw;
199 |   this.setOptions = setOptions;
200 | 
201 |   this.Width = width || canvas.width;
202 |   this.Height = height || canvas.height;
203 | 
204 |   this.Canvas = canvas;
205 |   this.CalcPoints();
206 |   this.ElementArray.SetCount(count);
207 | 
208 |   function setOptions(options){
209 |     if (options.elements)
210 |       this.ElementArray.SetCount(options.elements);
211 | 
212 |     this.SegmentWidth = options.segmentWidth || this.SegmentWidth;
213 |     this.SegmentInterval = options.segmentInterval || this.SegmentInterval;
214 |     this.BevelWidth = 0.01;
215 |     this.SideBevelEnabled = true;
216 |     this.StrokeLight = options.color || this.StrokeLight;
217 | 
218 |     this.StrokeWidth = options.strokeWidth || this.StrokeWidth;
219 |     this.Padding = options.elementPadding || this.Padding;
220 |     this.Spacing = options.elementSpacing || this.Spacing;
221 | 
222 |     this.ElementWidth = (width - (this.Spacing*count))/count;
223 |     this.ElementHeight = height - (this.Padding*2);
224 |   }
225 | 
226 |   function DisplayText(value) {
227 |     // Recalculate points in case any settings changed
228 |     // console.error("si: %s, sw: %s", this.SegmentInterval, this.SegmentWidth);
229 |     // console.error("st: %s", this.StrokeWidth);
230 |     // Set the display patterns and draw the canvas
231 |     this.ElementArray.SetText(value, CharacterMasks);
232 |     this.CalcPoints();
233 |     this.Draw(this.Canvas, this.ElementArray.Elements);
234 |   }
235 | 
236 |   function CalcElementDimensions() {
237 |     var n = this.ElementCount;
238 |     var h = this.ElementHeight;
239 |     h -= this.Padding * 2;
240 | 
241 |     var w = this.Width;
242 |     w -= this.Spacing * (n - 1);
243 |     w -= this.Padding * 2;
244 |     w /= n;
245 |     var output = { Width: w, Height: h };
246 |     // console.error(output);
247 |     return output;
248 |   }
249 | 
250 |   function FlipVertical(points, height) {
251 |     var flipped = [];
252 |     for(var i=0;i<points.length;i++) {
253 |       flipped[i] = {};
254 |       flipped[i].x = points[i].x;
255 |       flipped[i].y = height - points[i].y;
256 |     }
257 |     return flipped;
258 |   }
259 | 
260 |   function FlipHorizontal(points, width) {
261 |     var flipped = [];
262 |     for(var i=0;i<points.length;i++) {
263 |       flipped[i] = {};
264 |       flipped[i].x = width - points[i].x;
265 |       flipped[i].y = points[i].y;
266 |     }
267 |     return flipped;
268 |   }
269 | 
270 |   function Draw(context, elements) {
271 |     // Get the context and clear the area
272 |     context.clearRect(this.X, this.Y, this.Width, this.Height);
273 |     context.save();
274 | 
275 |     // Calculate the width and spacing of each element
276 |     var elementWidth = this.CalcElementDimensions().Width;
277 |     // console.error("width: %s", elementWidth);
278 |     // Offset to adjust for starting point and padding
279 |     context.translate(this.X, this.Y);
280 |     context.translate(this.Padding, this.Padding);
281 | 
282 |     // Draw each segment of each element
283 |     for (var i = 0; i < elements.length; i++) {
284 |       var element = elements[i];
285 |       for (var s = 0; s < this.Points.length; s++) {
286 |         // Pick the on or off color based on the bitmask
287 |         var color = (element & 1 << s) ? this.FillLight : this.FillDark;
288 |         var stroke = (element & 1 << s) ? this.StrokeLight : this.StrokeDark;
289 |         if (stroke == this.StrokeDark) continue;
290 |         // console.error("c: %s, s: %s", color, stroke);
291 |         context.lineWidth = this.StrokeWidth;
292 |         context.strokeStyle = stroke;
293 |         context.fillStyle = color;
294 |         context.moveTo(0,0);
295 |         context.beginPath();
296 |         context.moveTo(this.Points[s][0].x, this.Points[s][0].y);
297 |         // Create the segment path
298 |         var maxX = 0;
299 |         for(var p = 1; p < this.Points[s].length; p++) {
300 |           if (this.Points[s][p].x > maxX)
301 |             maxX = this.Points[s][p].x;
302 |           context.lineTo(Math.round(this.Points[s][p].x), Math.round(this.Points[s][p].y));
303 |         }
304 |         context.closePath();
305 |         context.fill();
306 |         context.stroke();
307 |         if (this.StrokeWidth > 0) {
308 |           context.stroke();
309 |         }
310 |       }
311 |       context.translate(elementWidth+this.Spacing, 0);
312 |     }
313 |     context.restore();
314 |   }
315 | 
316 |   function CalcPoints() {
317 |     var w = this.ElementWidth,
318 |       h = this.ElementHeight,
319 |       sw = this.SegmentWidth * w,
320 |       si = this.SegmentInterval * w,
321 |       bw = this.BevelWidth * sw,
322 |       ib = (this.SideBevelEnabled) ? 1 : 0,
323 |       sf = sw * 0.8,
324 |       slope = h / w,
325 |       sqrt2 = Math.SQRT2,
326 |       sqrt3 = Math.sqrt(3);
327 | 
328 |     // Base position of points w/out bevel and interval
329 |     var w0 = w / 2 - sw / 2,        h0 = 0,
330 |       w1 = w / 2,                 h1 = sw / 2,
331 |       w2 = w / 2 + sw / 2,        h2 = sw,
332 |       w3 = w - sw,                h3 = h / 2 - sw / 2,
333 |       w4 = w - sw / 2,            h4 = h / 2,
334 |       w5 = w,                     h5 = h / 2 + sw / 2;
335 | 
336 |     // Order of segments stored in Points[][]
337 |     var A1 = 0, A2 = 1, B = 2,  C = 3,  D1 = 4, D2 = 5, E = 6,  F = 7,
338 |       G1 = 8, G2 = 9, H = 10, I = 11, J = 12, K = 13, L = 14, M = 15;
339 | 
340 |     // Create the points array for all segments
341 |     var points = [];
342 |     points[A1] = [
343 |       { x: bw * 2 + si / sqrt2,           y: h0        },
344 |       { x: w1 - si / 2 - sw / 2 * ib,     y: h0        },
345 |       { x: w1 - si / 2,                   y: h1        },
346 |       { x: w0 - si / 2,                   y: h2        },
347 |       { x: sw + si / sqrt2,               y: h2        },
348 |       { x: bw + si / sqrt2,               y: h0 + bw   }
349 |     ];
350 |     points[G2] = [
351 |       { x: w2 + si / sqrt2,               y: h3        },
352 |       { x: w3 - si / 2 * sqrt3,           y: h3        },
353 |       { x: w4 - si / 2 * sqrt3,           y: h4        },
354 |       { x: w3 - si / 2 * sqrt3,           y: h5        },
355 |       { x: w2 + si / sqrt2,               y: h5        },
356 |       { x: w1 + si / sqrt2,               y: h4        }
357 |     ];
358 |     points[B] = [
359 |       { x: w5,           y: h0 + bw * 2 + si / sqrt2   },
360 |       { x: w5,           y: h4 - si / 2 - sw / 2 * ib  },
361 |       { x: w4,           y: h4 - si / 2                },
362 |       { x: w3,           y: h3 - si / 2                },
363 |       { x: w3,           y: h2 + si / sqrt2            },
364 |       { x: w5 - bw,      y: h0 + bw + si / sqrt2       }
365 |     ];
366 |     points[I] = [
367 |       { x: w2,           y: h2 + si / 2 * sqrt3        },
368 |       { x: w2,           y: h3 - si / sqrt2            },
369 |       { x: w1,           y: h4 - si / sqrt2            },
370 |       { x: w0,           y: h3 - si / sqrt2            },
371 |       { x: w0,           y: h2 + si / 2 * sqrt3        },
372 |       { x: w1,           y: h1 + si / 2 * sqrt3        }
373 |     ];
374 |     points[H] = [
375 |       { x: (sw + sf) / slope + si,        y: h2 + si              },
376 |       { x: w0 - si,                       y: w0 * slope - sf - si },
377 |       { x: w0 - si,                       y: h3 - si              },
378 |       { x: (h3 - sf) / slope - si,        y: h3 - si              },
379 |       { x: sw + si,                       y: h2 * slope + sf + si },
380 |       { x: sw + si,                       y: h2 + si              }
381 |     ];
382 |     points[A2] = this.FlipHorizontal(points[A1], w);    // A2
383 |     points[C]  = this.FlipVertical(points[2], h);       // C
384 |     points[D1] = this.FlipVertical(points[0], h);       // D1
385 |     points[D2] = this.FlipHorizontal(points[4], w);     // D2
386 |     points[E]  = this.FlipHorizontal(points[3], w);     // E
387 |     points[F]  = this.FlipHorizontal(points[2], w);     // F
388 |     points[G1] = this.FlipHorizontal(points[9], w);     // G1
389 |     points[J]  = this.FlipHorizontal(points[10], w);    // J
390 |     points[K]  = this.FlipVertical(points[12], h);      // K
391 |     points[L]  = this.FlipVertical(points[11], h);      // L
392 |     points[M]  = this.FlipVertical(points[10], h);      // M
393 |     this.Points = points;
394 |   }
395 | }
396 | var CharacterMasks = (function() {
397 |   // Segment Bitmasks for individual segments.
398 |   // Binary Or them together to create bitmasks
399 |   // a1|a2|b|c|d1|d2|e|f|g1|g2|h|i|j|k|l|m
400 |   var a1 = 1 << 0,    a2 = 1 << 1,    b = 1 << 2,    c = 1 << 3,
401 |     d1 = 1 << 4,    d2 = 1 << 5,    e = 1 << 6,    f = 1 << 7,
402 |     g1 = 1 << 8,    g2 = 1 << 9,    h = 1 << 10,   i = 1 << 11,
403 |     j  = 1 << 12,   k  = 1 << 13,   l = 1 << 14,   m = 1 << 15;
404 |   // Character map associates characters with a bit pattern
405 |   return {
406 |     ' ' : 0,
407 |     ''  : 0,
408 |     '0' : a1|a2|b|c|d1|d2|e|f|j|m,
409 |     '1' : b|c|j,
410 |     '2' : a1|a2|b|d1|d2|e|g1|g2,
411 |     '3' : a1|a2|b|c|d1|d2|g2,
412 |     '4' : b|c|f|g1|g2,
413 |     '5' : a1|a2|c|d1|d2|f|g1|g2,
414 |     '6' : a1|a2|c|d1|d2|e|f|g1|g2,
415 |     '7' : a1|a2|b|c,
416 |     '8' : a1|a2|b|c|d1|d2|e|f|g1|g2,
417 |     '9' : a1|a2|b|c|f|g1|g2,
418 |     'A' : e|f|a1|a2|b|c|g1|g2,
419 |     'B' : a1|a2|b|c|d1|d2|g2|i|l,
420 |     'C' : a1|a2|f|e|d1|d2,
421 |     'D' : a1|a2|b|c|d1|d2|i|l,
422 |     'E' : a1|a2|f|e|d1|d2|g1|g2,
423 |     'F' : a1|a2|e|f|g1 ,
424 |     'G' : a1|a2|c|d1|d2|e|f|g2,
425 |     'H' : b|c|e|f|g1|g2,
426 |     'I' : a1|a2|d1|d2|i|l,
427 |     'J' : b|c|d1|d2|e,
428 |     'K' : e|f|g1|j|k,
429 |     'L' : d1|d2|e|f,
430 |     'M' : b|c|e|f|h|j,
431 |     'N' : b|c|e|f|h|k,
432 |     'O' : a1|a2|b|c|d1|d2|e|f,
433 |     'P' : a1|a2|b|e|f|g1|g2,
434 |     'Q' : a1|a2|b|c|d1|d2|e|f|k,
435 |     'R' : a1|a2|b|e|f|g1|g2|k,
436 |     'S' : a1|a2|c|d1|d2|f|g1|g2,
437 |     'T' : a1|a2|i|l,
438 |     'U' : b|c|d1|d2|e|f,
439 |     'V' : e|f|j|m,
440 |     'W' : b|c|e|f|k|m,
441 |     'X' : h|j|k|m,
442 |     'Y' : b|f|g1|g2|l,
443 |     'Z' : a1|a2|d1|d2|j|m,
444 |     '-' : g1|g2,
445 |     '?' : a1|a2|b|g2|l,
446 |     '+' : g1|g2|i|l,
447 |     '*' : g1|g2|h|i|j|k|l|m
448 |   };
449 | }());
450 | 
451 | module.exports = LCD;
452 | 


--------------------------------------------------------------------------------
/lib/widget/log.js:
--------------------------------------------------------------------------------
 1 | 'use strict';
 2 | var blessed = require('blessed')
 3 |   , Node = blessed.Node
 4 |   , List = blessed.List;
 5 | 
 6 | function Log(options) {
 7 |   if (!(this instanceof Node)) {
 8 |     return new Log(options);
 9 |   }
10 | 
11 |   options = options || {};
12 |   options.bufferLength = options.bufferLength || 30;
13 |   this.options = options;
14 |   List.call(this, options);
15 | 
16 |   this.logLines = [];
17 |   this.interactive = false;
18 | }
19 | 
20 | Log.prototype = Object.create(List.prototype);
21 | 
22 | Log.prototype.log = function(str) {
23 |   this.logLines.push(str);
24 |   if (this.logLines.length>this.options.bufferLength) {
25 |     this.logLines.shift();
26 |   }
27 |   this.setItems(this.logLines);
28 |   this.scrollTo(this.logLines.length);
29 | };
30 | 
31 | Log.prototype.type = 'log';
32 | 
33 | module.exports = Log;
34 | 


--------------------------------------------------------------------------------
/lib/widget/map.js:
--------------------------------------------------------------------------------
 1 | 'use strict';
 2 | var blessed = require('blessed')
 3 |   , Node = blessed.Node
 4 |   , Canvas = require('./canvas')
 5 |   , InnerMap = require('map-canvas');
 6 | 
 7 | function Map(options) {
 8 |   var self = this;
 9 | 
10 |   if (!(this instanceof Node)) {
11 |     return new Map(options);
12 |   }
13 | 
14 |   Canvas.call(this, options);
15 | 
16 |   this.on('attach', function() {
17 | 
18 |     options.style = options.style || {};
19 | 
20 |     var opts = { excludeAntartica: (options.excludeAntarctica === undefined) ? true : options.excludeAntarctica
21 |       , disableBackground: (options.disableBackground === undefined) ? true : options.disableBackground
22 |       , disableMapBackground: (options.disableMapBackground === undefined) ? true : options.disableMapBackground
23 |       , disableGraticule: (options.disableGraticule === undefined) ? true : options.disableGraticule
24 |       , disableFill: (options.disableFill === undefined) ? true : options.disableFill
25 |       , width: self.ctx._canvas.width
26 |       , height: self.ctx._canvas.height
27 |       , shapeColor: options.style.shapeColor || 'green'};
28 | 
29 |     opts.startLon = options.startLon || undefined;
30 |     opts.endLon = options.endLon || undefined;
31 |     opts.startLat = options.startLat || undefined;
32 |     opts.endLat = options.endLat || undefined;
33 |     opts.region = options.region || undefined;
34 |     opts.labelSpace = options.labelSpace || 5;
35 | 
36 |     this.ctx.strokeStyle= options.style.stroke || 'green';
37 |     this.ctx.fillStyle=options.style.fill || 'green';
38 | 
39 |     self.innerMap = new InnerMap(opts, this._canvas);
40 |     self.innerMap.draw();
41 | 
42 |     if (self.options.markers) {
43 | 
44 |       for (var m in self.options.markers) {
45 |         self.addMarker(self.options.markers[m]);
46 |       }
47 |     }
48 |   });
49 | 
50 | }
51 | 
52 | Map.prototype = Object.create(Canvas.prototype);
53 | 
54 | Map.prototype.calcSize = function() {
55 |   this.canvasSize = {width: this.width*2-12, height: this.height*4};
56 | };
57 | 
58 | Map.prototype.type = 'map';
59 | 
60 | Map.prototype.addMarker = function(options) {
61 |   if (!this.innerMap) {
62 |     throw 'error: canvas context does not exist. addMarker() for maps must be called after the map has been added to the screen via screen.append()';
63 |   }
64 | 
65 |   this.innerMap.addMarker(options);
66 | };
67 | 
68 | Map.prototype.getOptionsPrototype = function() {
69 | 
70 |   return { startLon: 10
71 |     , endLon: 10
72 |     , startLat: 10
73 |     , endLat: 10
74 |     , region: 'us'
75 |     , markers:
76 |              [  {'lon' : '-79.0000', 'lat' : '37.5000', color: 'red', char: 'X' }
77 |                ,{'lon' : '79.0000', 'lat' : '37.5000', color: 'blue', char: 'O' }
78 |              ]
79 |   };
80 | };
81 | 
82 | Map.prototype.clearMarkers = function() {
83 |   this.innerMap.draw();
84 | };
85 | 
86 | module.exports = Map;
87 | 


--------------------------------------------------------------------------------
/lib/widget/markdown.js:
--------------------------------------------------------------------------------
 1 | 'use strict';
 2 | var blessed = require('blessed')
 3 |   , Box = blessed.Box
 4 |   , marked = require('marked')
 5 |   , TerminalRenderer = require('marked-terminal')
 6 |   , chalk = require('chalk');
 7 | 
 8 | 
 9 | function Markdown(options) {
10 |   if (!(this instanceof Box)) {
11 |     return new Markdown(options);
12 |   }
13 | 
14 |   options = options || {};
15 | 
16 |   const markdownOptions = {
17 |     style: options.markdownStyle
18 |   };
19 | 
20 |   this.evalStyles(markdownOptions);
21 | 
22 |   this.setOptions(markdownOptions.style);
23 | 
24 |   this.options = options;
25 |   Box.call(this, options);
26 | 
27 |   if (options.markdown) this.setMarkdown(options.markdown);
28 | }
29 | 
30 | Markdown.prototype = Object.create(Box.prototype);
31 | 
32 | Markdown.prototype.setMarkdown = function(str) {
33 |   this.setContent(marked.parse(str));
34 | };
35 | 
36 | Markdown.prototype.setOptions = function(style) {
37 |   marked.setOptions({
38 |     renderer: new TerminalRenderer(style)
39 |   });
40 | };
41 | 
42 | Markdown.prototype.evalStyles = function(options) {
43 |   if (!options.style) return;
44 |   for (var st in options.style) {
45 |     if (typeof(options.style[st])!='string') continue;
46 | 
47 |     var tokens = options.style[st].split('.');
48 |     options.style[st] = chalk;
49 |     for (var j=1; j<tokens.length; j++) {
50 |       options.style[st] = options.style[st][tokens[j]];
51 |     }
52 |   }
53 | };
54 | 
55 | Markdown.prototype.getOptionsPrototype = function() {
56 |   return {
57 |     markdown: 'string',
58 |     markdownStyle: 'object'
59 |   };
60 | };
61 | 
62 | Markdown.prototype.type = 'markdown';
63 | 
64 | module.exports = Markdown;
65 | 


--------------------------------------------------------------------------------
/lib/widget/picture.js:
--------------------------------------------------------------------------------
 1 | 'use strict';
 2 | var blessed = require('blessed')
 3 |   , Node = blessed.Node
 4 |   , Box = blessed.Box
 5 |   , pictureTube = require('picture-tuber')
 6 |   , fs = require('fs')
 7 |   , streams = require('memory-streams')
 8 |   , MemoryStream = require('memorystream');
 9 | 
10 | function Picture(options) {
11 |   if (!(this instanceof Node)) {
12 |     return new Picture(options);
13 |   }
14 | 
15 |   options = options || {};
16 |   options.cols = options.cols || 50;
17 |   this.options = options;
18 | 
19 |   if (options.file || options.base64) {
20 |     this.setImage(options);
21 |   }
22 | 
23 |   Box.call(this, options);
24 | }
25 | 
26 | Picture.prototype = Object.create(Box.prototype);
27 | 
28 | Picture.prototype.setImage = function(options) {
29 | 
30 |   var tube = pictureTube( { cols: options.cols } );
31 | 
32 |   if (options.file) fs.createReadStream(options.file).pipe(tube);
33 |   else if (options.base64) {
34 |     var memStream = new MemoryStream();
35 |     memStream.pipe(tube);
36 |     var buf = new Buffer(options.base64, 'base64');
37 |     memStream.write(buf);
38 |     memStream.end();
39 |   }
40 | 
41 |   this.writer = new streams.WritableStream();
42 |   tube.pipe(this.writer);
43 | 
44 |   tube.on('end', function() {
45 |     if (options.onReady) {
46 |       options.onReady();
47 |     }
48 |   });
49 | 
50 | };
51 | 
52 | Picture.prototype.render = function() {
53 |   this.setContent(this.writer.toString());
54 |   return this._render();
55 | };
56 | 
57 | Picture.prototype.getOptionsPrototype = function() {
58 | 
59 |   return { base64:'AAAA'
60 |     , cols: 1 };
61 | 
62 | };
63 | 
64 | Picture.prototype.type = 'picture';
65 | 
66 | module.exports = Picture;
67 | 


--------------------------------------------------------------------------------
/lib/widget/sparkline.js:
--------------------------------------------------------------------------------
 1 | 'use strict';
 2 | var blessed = require('blessed')
 3 |   , Node = blessed.Node
 4 |   , Box = blessed.Box
 5 |   , sparkline = require('sparkline');
 6 | 
 7 | function Sparkline(options) {
 8 | 
 9 |   var self = this;
10 | 
11 |   if (!(this instanceof Node)) {
12 |     return new Sparkline(options);
13 |   }
14 | 
15 |   options = options || {};
16 |   options.bufferLength = options.bufferLength || 30;
17 |   options.style = options.style || {};
18 |   options.style.titleFg = options.style.titleFg || 'white';
19 |   this.options = options;
20 |   Box.call(this, options);
21 | 
22 | 
23 |   this.on('attach', function() {
24 |     if (self.options.data) {
25 |       self.setData(self.options.data.titles, self.options.data.data);
26 |     }
27 |   });
28 | }
29 | 
30 | Sparkline.prototype = Object.create(Box.prototype);
31 | 
32 | Sparkline.prototype.setData = function(titles, datasets) {
33 |   var res = '\r\n';
34 |   for (var i=0; i<titles.length; i++) {
35 |     res += '{bold}{'+this.options.style.titleFg+'-fg}' + titles[i]+':{/'+this.options.style.titleFg+'-fg}{/bold}\r\n';
36 |     res += sparkline(datasets[i].slice(0, this.width-2)) + '\r\n\r\n';
37 |   }
38 | 
39 |   this.setContent(res);
40 | };
41 | 
42 | Sparkline.prototype.getOptionsPrototype = function() {
43 |   return { label: 'Sparkline'
44 |     , tags: true
45 |     , border: {type: 'line', fg: 'cyan'}
46 |     , width: '50%'
47 |     , height: '50%'
48 |     , style: { fg: 'blue' }
49 |     , data: { titles: [ 'Sparkline1', 'Sparkline2'],
50 |       data: [ [10, 20, 30, 20, 50, 70, 60, 30, 35, 38]
51 |         , [40, 10, 40, 50, 20, 30, 20, 20, 19, 40] ]
52 |     }
53 |   };
54 | };
55 | 
56 | Sparkline.prototype.type = 'sparkline';
57 | 
58 | module.exports = Sparkline;
59 | 


--------------------------------------------------------------------------------
/lib/widget/table.js:
--------------------------------------------------------------------------------
  1 | 'use strict';
  2 | var blessed = require('blessed')
  3 |   , Node = blessed.Node
  4 |   , Box = blessed.Box
  5 |   , stripAnsi = require('strip-ansi');
  6 | 
  7 | function Table(options) {
  8 | 
  9 |   var self = this;
 10 | 
 11 |   if (!(this instanceof Node)) {
 12 |     return new Table(options);
 13 |   }
 14 | 
 15 |   if (Array.isArray(options.columnSpacing)) {
 16 |     throw 'Error: columnSpacing cannot be an array.\r\n' +
 17 |            'Note: From release 2.0.0 use property columnWidth instead of columnSpacing.\r\n' +
 18 |            'Please refere to the README or to https://github.com/yaronn/blessed-contrib/issues/39';
 19 |   }
 20 | 
 21 |   if (!options.columnWidth) {
 22 |     throw 'Error: A table must get columnWidth as a property. Please refer to the README.';
 23 |   }
 24 | 
 25 |   options = options || {};
 26 |   options.columnSpacing = options.columnSpacing==null? 10 : options.columnSpacing;
 27 |   options.bold = true;
 28 |   options.selectedFg = options.selectedFg || 'white';
 29 |   options.selectedBg = options.selectedBg || 'blue';
 30 |   options.fg = options.fg || 'green';
 31 |   options.bg = options.bg || '';
 32 |   options.interactive = (typeof options.interactive === 'undefined') ? true : options.interactive;
 33 |   this.options = options;
 34 |   Box.call(this, options);
 35 | 
 36 |   this.rows = blessed.list({
 37 |     //height: 0,
 38 |     top: 2,
 39 |     width: 0,
 40 |     left: 1,
 41 |     style: { selected: {
 42 |       fg: options.selectedFg
 43 |       , bg: options.selectedBg
 44 |     }
 45 |     , item: {
 46 |       fg: options.fg
 47 |       , bg: options.bg
 48 |     }},
 49 |     keys: options.keys,
 50 |     vi: options.vi,
 51 |     mouse: options.mouse,
 52 |     tags: true,
 53 |     interactive: options.interactive,
 54 |     screen: this.screen
 55 |   });
 56 | 
 57 |   this.append(this.rows);
 58 | 
 59 |   this.on('attach', function() {
 60 |     if (self.options.data) {
 61 |       self.setData(self.options.data);
 62 |     }
 63 |   });
 64 | 
 65 | }
 66 | 
 67 | Table.prototype = Object.create(Box.prototype);
 68 | 
 69 | Table.prototype.focus = function(){
 70 |   this.rows.focus();
 71 | };
 72 | 
 73 | Table.prototype.render = function() {
 74 |   if(this.screen.focused == this.rows)
 75 |     this.rows.focus();
 76 | 
 77 |   this.rows.width = this.width-3;
 78 |   this.rows.height = this.height-4;
 79 |   Box.prototype.render.call(this);
 80 | };
 81 | 
 82 | 
 83 | Table.prototype.setData = function(table) {
 84 |   var self = this;
 85 | 
 86 |   var dataToString = function(d) {
 87 |     var str = '';
 88 |     d.forEach(function(r, i) {
 89 |       var colsize = self.options.columnWidth[i]
 90 |         , strip = stripAnsi(r.toString())
 91 |         , ansiLen = r.toString().length - strip.length
 92 |         , spaceLength = colsize - strip.length + self.options.columnSpacing;
 93 |       r = r.toString().substring(0, colsize + ansiLen); //compensate for ansi len
 94 |       if (spaceLength < 0) {
 95 |         spaceLength = 0;
 96 |       }
 97 |       var spaces = new Array(spaceLength).join(' ');
 98 |       str += r + spaces;
 99 |     });
100 |     return str;
101 |   };
102 | 
103 |   var formatted = [];
104 | 
105 |   table.data.forEach(function(d) {
106 |     var str = dataToString(d);
107 |     formatted.push(str);
108 |   });
109 |   this.setContent(dataToString(table.headers));
110 |   this.rows.setItems(formatted);
111 | };
112 | 
113 | Table.prototype.getOptionsPrototype = function() {
114 |   return  { keys: true
115 |     , fg: 'white'
116 |     , interactive: false
117 |     , label: 'Active Processes'
118 |     , width: '30%'
119 |     , height: '30%'
120 |     , border: {type: 'line', fg: 'cyan'}
121 |     , columnSpacing: 10
122 |     , columnWidth: [16, 12]
123 |     , data: { headers: ['col1', 'col2']
124 |       , data: [ ['a', 'b']
125 |         , ['5', 'u']
126 |         , ['x', '16.1'] ]}
127 |   };
128 | };
129 | 
130 | Table.prototype.type = 'table';
131 | 
132 | module.exports = Table;
133 | 


--------------------------------------------------------------------------------
/lib/widget/tree.js:
--------------------------------------------------------------------------------
  1 | 'use strict';
  2 | var blessed = require('blessed'),
  3 |   Node = blessed.Node,
  4 |   Box = blessed.Box;
  5 | 
  6 | function Tree(options) {
  7 |   if (!(this instanceof Node)) {
  8 |     return new Tree(options);
  9 |   }
 10 | 
 11 |   var self = this;
 12 |   options = options || {};
 13 |   options.bold = true;
 14 |   this.options = options;
 15 |   this.data = {};
 16 |   this.nodeLines = [];
 17 |   this.lineNbr = 0;
 18 |   Box.call(this, options);
 19 | 
 20 |   options.extended = options.extended || false;
 21 |   options.keys = options.keys || ['+', 'space', 'enter'];
 22 | 
 23 |   options.template = options.template || {};
 24 |   options.template.extend = options.template.extend || ' [+]';
 25 |   options.template.retract = options.template.retract || ' [-]';
 26 |   options.template.lines = options.template.lines || false;
 27 | 
 28 |   // Do not set height, since this create a bug where the first line is not always displayed
 29 |   this.rows = blessed.list({
 30 |     top: 1,
 31 |     width: 0,
 32 |     left: 1,
 33 |     style: options.style,
 34 |     padding: options.padding,
 35 |     keys: true,
 36 |     tags: options.tags,
 37 |     input: options.input,
 38 |     vi: options.vi,
 39 |     ignoreKeys: options.ignoreKeys,
 40 |     scrollable: options.scrollable,
 41 |     mouse: options.mouse,
 42 |     selectedBg: options.selectedBg || 'blue',
 43 |     selectedFg: options.selectedFg || 'black',
 44 |   });
 45 | 
 46 |   this.append(this.rows);
 47 | 
 48 |   this.rows.key(options.keys, function() {
 49 |     var selectedNode = self.nodeLines[this.getItemIndex(this.selected)];
 50 |     if (selectedNode.children) {
 51 |       selectedNode.extended = !selectedNode.extended;
 52 |       self.setData(self.data);
 53 |       self.screen.render();
 54 |     }
 55 | 
 56 |     self.emit('select', selectedNode, this.getItemIndex(this.selected));
 57 |   });
 58 | 
 59 | }
 60 | 
 61 | Tree.prototype = Object.create(Box.prototype);
 62 | 
 63 | Tree.prototype.walk = function(node, treeDepth) {
 64 | 
 65 |   var lines = [];
 66 | 
 67 |   if (!node.parent) {
 68 |     // root level
 69 |     this.lineNbr = 0;
 70 |     this.nodeLines.length = 0;
 71 |     node.parent = null;
 72 |   }
 73 | 
 74 |   if (treeDepth === '' && node.name) {
 75 |     this.lineNbr = 0;
 76 |     this.nodeLines[this.lineNbr++] = node;
 77 |     lines.push(node.name);
 78 |     treeDepth = ' ';
 79 |   }
 80 | 
 81 |   node.depth = treeDepth.length - 1;
 82 | 
 83 |   if (node.children && node.extended) {
 84 | 
 85 |     var i = 0;
 86 | 
 87 |     if (typeof node.children === 'function')
 88 |       node.childrenContent = node.children(node);
 89 | 
 90 |     if (!node.childrenContent)
 91 |       node.childrenContent = node.children;
 92 | 
 93 |     for (var child in node.childrenContent) {
 94 | 
 95 |       if (!node.childrenContent[child].name)
 96 |         node.childrenContent[child].name = child;
 97 | 
 98 |       child = node.childrenContent[child];
 99 |       child.parent = node;
100 |       child.position = i++;
101 | 
102 |       if (typeof child.extended === 'undefined')
103 |         child.extended = this.options.extended;
104 | 
105 |       if (typeof child.children === 'function')
106 |         child.childrenContent = child.children(child);
107 |       else
108 |         child.childrenContent = child.children;
109 | 
110 |       var isLastChild = child.position === Object.keys(child.parent.childrenContent).length - 1;
111 |       var treePrefix;
112 |       var suffix = '';
113 |       if (isLastChild)
114 |         treePrefix = '└';
115 |       else
116 |         treePrefix = '├';
117 | 
118 |       if (!child.childrenContent || Object.keys(child.childrenContent).length === 0) {
119 |         treePrefix += '─';
120 |       } else if (child.extended) {
121 |         treePrefix += '┬';
122 |         suffix = this.options.template.retract;
123 |       } else {
124 |         treePrefix += '─';
125 |         suffix = this.options.template.extend;
126 |       }
127 | 
128 |       if (!this.options.template.lines) treePrefix = '|-';
129 |       if (this.options.template.spaces) treePrefix = ' ';
130 | 
131 |       lines.push(treeDepth + treePrefix + child.name + suffix);
132 | 
133 |       this.nodeLines[this.lineNbr++] = child;
134 | 
135 |       var parentTree;
136 |       if (isLastChild || !this.options.template.lines)
137 |         parentTree = treeDepth + ' ';
138 |       else
139 |         parentTree = treeDepth + '│';
140 | 
141 |       lines = lines.concat(this.walk(child, parentTree));
142 |     }
143 |   }
144 |   return lines;
145 | };
146 | 
147 | Tree.prototype.focus = function() {
148 |   this.rows.focus();
149 | };
150 | 
151 | Tree.prototype.render = function() {
152 |   if (this.screen.focused === this.rows) this.rows.focus();
153 | 
154 |   this.rows.width = this.width - 3;
155 |   this.rows.height = this.height - 3;
156 |   Box.prototype.render.call(this);
157 | };
158 | 
159 | Tree.prototype.setData = function(nodes) {
160 |   this.data = nodes;
161 |   this.rows.setItems(this.walk(nodes, ''));
162 | };
163 | 
164 | Tree.prototype.type = 'tree';
165 | 
166 | module.exports = Tree;
167 | 


--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
 1 | {
 2 |   "name": "blessed-contrib",
 3 |   "version": "4.11.0",
 4 |   "description": "",
 5 |   "main": "index.js",
 6 |   "types": "index.d.ts",
 7 |   "scripts": {
 8 |     "test": "npm run lint",
 9 |     "lint": "eslint lib",
10 |     "lint:fix": "eslint lib --fix"
11 |   },
12 |   "repository": {
13 |     "type": "git",
14 |     "url": "https://github.com/yaronn/blessed-contrib.git"
15 |   },
16 |   "author": "Yaron Naveh (yaronn01@gmail.com)",
17 |   "license": "MIT",
18 |   "devDependencies": {
19 |     "@types/blessed": "^0.1.6",
20 |     "blessed": "0.1.54",
21 |     "colors": "^1.1.2",
22 |     "eslint": "^5.11.0",
23 |     "eslint-config-standard": "^12.0.0",
24 |     "eslint-plugin-import": "^2.14.0",
25 |     "eslint-plugin-node": "^8.0.0",
26 |     "eslint-plugin-promise": "^4.0.1",
27 |     "eslint-plugin-standard": "^4.0.0"
28 |   },
29 |   "dependencies": {
30 |     "ansi-term": ">=0.0.2",
31 |     "chalk": "^1.1.0",
32 |     "drawille-canvas-blessed-contrib": ">=0.1.3",
33 |     "lodash": "~>=4.17.21",
34 |     "map-canvas": ">=0.1.5",
35 |     "marked": "^4.0.12",
36 |     "marked-terminal": "^5.1.1",
37 |     "memory-streams": "^0.1.0",
38 |     "memorystream": "^0.3.1",
39 |     "picture-tuber": "^1.0.1",
40 |     "sparkline": "^0.1.1",
41 |     "strip-ansi": "^3.0.0",
42 |     "term-canvas": "0.0.5",
43 |     "x256": ">=0.0.1"
44 |   }
45 | }
46 | 


--------------------------------------------------------------------------------