- Notifications
You must be signed in to change notification settings - Fork841
Build terminal dashboards using ascii/ansi art and javascript
License
yaronn/blessed-contrib
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
Build dashboards (or any other application) using ascii/ansi art and javascript.
Friendly to terminals, ssh and developers. Extendsblessed with customdrawille and other widgets.
You should alsocheck WOPR: a markup for creating terminal reports, presentations and infographics.
Contributors:
Yaron Naveh (@YaronNaveh)Chris (@xcezzz)Miguel Valadas (@mvaladas)Liran Tal (@lirantal)
Demo (full size):
Running the demo
git clone https://github.com/yaronn/blessed-contrib.gitcd blessed-contribnpm installnode ./examples/dashboard.js
Works on Linux, OS X and Windows. For Windows follow thepre requisites.
npm install blessed blessed-contrib
You can use any of the default widgets ofblessed (texts, lists and etc) or the widgets added in blessed-contrib (described below). Alayout is optional but useful for dashboards. The widgets in blessed-contrib follow the same usage pattern:
varblessed=require('blessed'),contrib=require('blessed-contrib'),screen=blessed.screen(),line=contrib.line({style:{line:"yellow",text:"green",baseline:"black"},xLabelPadding:3,xPadding:5,label:'Title'}),data={x:['t1','t2','t3','t4'],y:[5,1,7,5]}screen.append(line)//must append before setting dataline.setData([data])screen.key(['escape','q','C-c'],function(ch,key){returnprocess.exit(0);});screen.render()
See below for a complete list of widgets.
varline=contrib.line({style:{line:"yellow",text:"green",baseline:"black"},xLabelPadding:3,xPadding:5,showLegend:true,wholeNumbersOnly:false//true=do not show fraction in y axis,label:'Title'})varseries1={title:'apples',x:['t1','t2','t3','t4'],y:[5,1,7,5]}varseries2={title:'oranges',x:['t1','t2','t3','t4'],y:[2,1,4,8]}screen.append(line)//must append before setting dataline.setData([series1,series2])
Examples:simple line chart,multiple lines,256 colors
varbar=contrib.bar({label:'Server Utilization (%)',barWidth:4,barSpacing:6,xOffset:0,maxHeight:9})screen.append(bar)//must append before setting databar.setData({titles:['bar1','bar2'],data:[5,10]})
bar=contrib.stackedBar({label:'Server Utilization (%)',barWidth:4,barSpacing:6,xOffset:0//, maxValue: 15,height:"40%",width:"50%",barBgColor:['red','blue','green']})screen.append(bar)bar.setData({barCategory:['Q1','Q2','Q3','Q4'],stackedCategory:['US','EU','AP'],data:[[7,7,5],[8,2,0],[0,0,0],[2,3,2]]})
varmap=contrib.map({label:'World Map'})map.addMarker({"lon" :"-79.0000","lat" :"37.5000",color:"red",char:"X"})
vargauge=contrib.gauge({label:'Progress',stroke:'green',fill:'white'})gauge.setPercent(25)
Either specify each stacked portion with apercent
andstroke
...
vargauge=contrib.gauge({label:'Stacked '})gauge.setStack([{percent:30,stroke:'green'},{percent:30,stroke:'magenta'},{percent:40,stroke:'cyan'}])
Or, you can just supply an array of numbers and random colors will be chosen.
vargauge=contrib.gauge({label:'Stacked Progress'})gauge.setStack([30,30,40])
vardonut=contrib.donut({label:'Test',radius:8,arcWidth:3,remainColor:'black',yPadding:2,data:[{percent:80,label:'web1',color:'green'}]});
Data passed in usespercent
andlabel
to draw the donut graph. Color is optional and defaults to green.
donut.setData([{percent:87,label:'rcp','color':'green'},{percent:43,label:'rcp','color':'cyan'},]);
Updating the donut is as easy as passing in an array tosetData
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.
You can also hardcode a specific numeric into the donut's core display instead of the percentage by passing anpercentAltNumber
property to the data, such as:
vardonut=contrib.donut({label:'Test',radius:8,arcWidth:3,remainColor:'black',yPadding:2,data:[{percentAltNumber:50,percent:80,label:'web1',color:'green'}]});
See an example of this in one of the donuts settings on./examples/donut.js
.
varlcd=contrib.lcd({segmentWidth:0.06// how wide are the segments in % so 50% = 0.5,segmentInterval:0.11// spacing between the segments in % so 50% = 0.550% = 0.5,strokeWidth:0.11// spacing between the segments in % so 50% = 0.5,elements:4// how many elements in the display. or how many characters can be displayed.,display:321// what should be displayed before first call to setDisplay,elementSpacing:4// spacing between each element,elementPadding:2// how far away from the edges to put the elements,color:'white'// color for the segments,label:'Storage Remaining'})
lcd.setDisplay(23+'G');// will display "23G"lcd.setOptions({})// adjust options at runtime
Please see theexamples/lcd.js for an example. The example provides keybindings to adjust thesegmentWidth
andsegmentInterval
andstrokeWidth
in real-time so that you can see how they manipulate the look and feel.
varlog=contrib.log({fg:"green",selectedFg:"green",label:'Server Log'})log.log("new log line")
(Also check the new blessedimage implementation which has several benefits over this one.)
varpic=contrib.picture({file:'./flower.png',cols:25,onReady:ready})functionready(){screen.render()}
note: only png images are supported
varspark=contrib.sparkline({label:'Throughput (bits/sec)',tags:true,style:{fg:'blue'}})sparkline.setData(['Sparkline1','Sparkline2'],[[10,20,30,20],[40,10,40,50]])
vartable=contrib.table({keys:true,fg:'white',selectedFg:'white',selectedBg:'blue',interactive:true,label:'Active Processes',width:'30%',height:'30%',border:{type:"line",fg:"cyan"},columnSpacing:10//in chars,columnWidth:[16,12,12]/*in chars*/})//allow control the table with the keyboardtable.focus()table.setData({headers:['col1','col2','col3'],data:[[1,2,3],[4,5,6]]})
vartree=contrib.tree({fg:'green'})//allow control the table with the keyboardtree.focus()tree.on('select',function(node){if(node.myCustomProperty){console.log(node.myCustomProperty);}console.log(node.name);}// you can specify a name property at root level to display roottree.setData({extended:true,children:{'Fruit':{children:{'Banana':{},'Apple':{},'Cherry':{},'Exotics':{children:{'Mango':{},'Papaya':{},'Kiwi':{name:'Kiwi (not the bird!)',myCustomProperty:"hairy fruit"}}},'Pear':{}}},'Vegetables':{children:{'Peas':{},'Lettuce':{},'Pepper':{}}}}})
- keys : Key to expand nodes. Default : ['enter','default']
- extended : Should nodes be extended/generated by default? Be careful with this setting when using a callback function. Default : false
- template :
- extend : Suffix "icon" for closed node. Default : '[+]'
- retract : Suffix "icon" for opened node. Default : '[-]'
- lines : Show lines in tree. Default : true
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 :
- name
- Type :
string
- Desc : Node name
- If the node isn't the root and you don't specify the name, will be set to hash key
- Example :
{ name: 'Fruit'}
- Type :
- children
- Type :
hash
orfunction(node){ return children }
- Desc : Node children.
- The function must return a hash that could have been used as children property
- If you use a function, the result will be stored in
node.childrenContent
andchildren
- Example :
- Hash :
{'Fruit':{ name: 'Fruit', children:{ 'Banana': {}, 'Cherry': {}}}}
- Function : see
examples/explorer.js
- Hash :
- Type :
- childrenContent
- Type :
hash
- Desc : Children content for internal usageDO NOT MODIFY
- If
node.children
is a hash,node.children===node.childrenContent
- If
node.children
is a function, it's used to store thenode.children()
result - You can read this property, but you should never write it.
- Usually this will be used to check
if(node.childrenContent)
in yournode.children
function to generate children only once
- Type :
- extended
- Type :
boolean
- Desc : Determine if this node is extended
- No effect when the node have no child
- Default value for each node will be
treeInstance.options.extended
if the nodeextended
option is not set - Example :
{'Fruit':{ name: 'Fruit', extended: true, children:{ 'Banana': {}, 'Cherry': {}}}}
- Type :
varmarkdown=contrib.markdown()markdown.setMarkdown('# Hello \n blessed-contrib renders markdown using `marked-terminal`')
You can use 256 colors (source):
functionrandomColor(){return[Math.random()*255,Math.random()*255,Math.random()*255]}line=contrib.line({ ...,style:{line:randomColor(),text:randomColor(),baseline:randomColor()}})
A grid layout can auto position your elements in a grid layout.When using a grid, you should not create the widgets, rather specify to the grid which widget to create and with which params.Each widget can span multiple rows and columns.
varscreen=blessed.screen()vargrid=newcontrib.grid({rows:12,cols:12,screen:screen})//grid.set(row, col, rowSpan, colSpan, obj, opts)varmap=grid.set(0,0,4,4,contrib.map,{label:'World Map'})varbox=grid.set(4,4,4,4,blessed.box,{content:'My Box'})screen.render()
A carousel layout switches between different views based on time or keyboard activity.One use case is an office dashboard with rotating views:
varblessed=require('blessed'),contrib=require('./'),screen=blessed.screen()functionpage1(screen){varmap=contrib.map()screen.append(map)}functionpage2(screen){varline=contrib.line({width:80,height:30,left:15,top:12,xPadding:5,label:'Title'})vardata=[{title:'us-east',x:['t1','t2','t3','t4'],y:[0,0.0695652173913043,0.11304347826087,2],style:{line:'red'}}]screen.append(line)line.setData(data)}screen.key(['escape','q','C-c'],function(ch,key){returnprocess.exit(0);});varcarousel=newcontrib.carousel([page1,page2],{screen:screen,interval:3000//how often to switch views (set 0 to never swicth automatically),controlKeys:true//should right and left keyboard arrows control view rotation})carousel.start()
Running the sample
git clone https://github.com/yaronn/blessed-contrib.gitcd blessed-contribnpm installnode ./examples/dashboard.js
Installation (for a custom dashboard)
npm install blessednpm install blessed-contrib
A simple dashboard
varblessed=require('blessed'),contrib=require('blessed-contrib'),screen=blessed.screen(),grid=newcontrib.grid({rows:1,cols:2,screen:screen})varline=grid.set(0,0,1,1,contrib.line,{style:{line:"yellow",text:"green",baseline:"black"},xLabelPadding:3,xPadding:5,label:'Stocks'})varmap=grid.set(0,1,1,1,contrib.map,{label:'Servers Location'})varlineData={x:['t1','t2','t3','t4'],y:[5,1,7,5]}line.setData([lineData])screen.key(['escape','q','C-c'],function(ch,key){returnprocess.exit(0);});screen.render()
Rich dashboard
Seesource code
If you see questions marks or some (or all) missign characters try running with these env vars to fix encoding / terminal:
$> LANG=en_US.utf8 TERM=xterm-256color node your-code.js
This library is under theMIT License
About
Build terminal dashboards using ascii/ansi art and javascript