refactor: socket.io client NSPs
This commit is contained in:
parent
27f7c5799d
commit
05772bc994
|
|
@ -1,14 +1,19 @@
|
|||
'use strict'
|
||||
|
||||
var blessed = require('blessed')
|
||||
var chalk = require('chalk')
|
||||
var async = require('async')
|
||||
var _ = require('lodash')
|
||||
|
||||
var widgets = require('./widgets')
|
||||
var conf = require('../util/conf')
|
||||
var Log = require('../util/log')
|
||||
|
||||
var ignoredENVKeys = ['LS_COLORS']
|
||||
var regJSON = /("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g
|
||||
|
||||
module.exports = Layout
|
||||
|
||||
var exiting = false
|
||||
/**
|
||||
* Create layout.
|
||||
* @param {Object} options
|
||||
|
|
@ -17,6 +22,7 @@ function Layout (options) {
|
|||
if (!(this instanceof Layout)) {
|
||||
return new Layout(options)
|
||||
}
|
||||
// initialize options
|
||||
options = _.clone(options || {})
|
||||
if (!options.hostname) {
|
||||
options.hostname = '127.0.0.1'
|
||||
|
|
@ -24,14 +30,20 @@ function Layout (options) {
|
|||
if (!options.port) {
|
||||
throw new Error('Port of socket.io server is required!')
|
||||
}
|
||||
options.sockets = options.sockets || {}
|
||||
this.options = options
|
||||
this._eles = {}
|
||||
this._procCount = 0
|
||||
this._data = {
|
||||
processCount: -1,
|
||||
sockets: options.sockets || {}
|
||||
}
|
||||
delete options.sockets
|
||||
this.options = options
|
||||
Object.freeze(this.options)
|
||||
}
|
||||
|
||||
/**
|
||||
* Render GUI.
|
||||
* @param {Monitor} monitor
|
||||
* @return {N/A}
|
||||
*/
|
||||
Layout.prototype.render = function (monitor) {
|
||||
var self = this
|
||||
|
|
@ -39,22 +51,19 @@ Layout.prototype.render = function (monitor) {
|
|||
|
||||
// Preparing all socket.io clients.
|
||||
async.series(Object.keys(conf.NSP).map(function (ns) {
|
||||
return function (callback) {
|
||||
var callbackOnce = _.once(callback)
|
||||
return function (next) {
|
||||
var nsl = ns.toLowerCase()
|
||||
if (options.sockets[nsl]) {
|
||||
return callbackOnce()
|
||||
if (self._data.sockets[nsl]) {
|
||||
return next()
|
||||
}
|
||||
|
||||
// connect to monitor
|
||||
monitor.connect(_.extend({
|
||||
namespace: conf.NSP[ns]
|
||||
}, options), function (socket) {
|
||||
console.info('Connected to', socket.nsp)
|
||||
callbackOnce(null, socket)
|
||||
}, function (err, socket) {
|
||||
}, options), function (err, socket) {
|
||||
if (err) {
|
||||
return callbackOnce(new Error('Failed to connect to [' + ns + '] due to ' + err.message))
|
||||
return next(new Error('Fatal to connect to ' + socket.nsp + ' due to ' + err))
|
||||
}
|
||||
next(null, socket)
|
||||
})
|
||||
}
|
||||
}), function (err, res) {
|
||||
|
|
@ -62,6 +71,7 @@ Layout.prototype.render = function (monitor) {
|
|||
console.error(err.message)
|
||||
return process.exit(0)
|
||||
}
|
||||
// muted logger.
|
||||
Log({
|
||||
level: 1000
|
||||
})
|
||||
|
|
@ -69,14 +79,15 @@ Layout.prototype.render = function (monitor) {
|
|||
res.forEach(function (socket) {
|
||||
connectedSockets[socket.nsp.replace(/^\/+/g, '')] = socket
|
||||
})
|
||||
self.sockets = _.extend(connectedSockets, options.sockets)
|
||||
delete options.sockets
|
||||
// cache sockets.
|
||||
_.extend(self._data.sockets, connectedSockets)
|
||||
|
||||
// render layout.
|
||||
self._observe()
|
||||
self._draw()
|
||||
|
||||
// refresh processes every 1s
|
||||
setInterval(function () {
|
||||
self._bindProcesses()
|
||||
self._processesTable()
|
||||
}, 1000)
|
||||
})
|
||||
}
|
||||
|
|
@ -87,108 +98,121 @@ Layout.prototype.render = function (monitor) {
|
|||
Layout.prototype._observe = function () {
|
||||
var self = this
|
||||
console.info('Listening socket events...')
|
||||
var socketSys = this._socket(conf.NSP.SYS)
|
||||
socketSys.on('procs', function (procs) {
|
||||
self._procs = {
|
||||
data: procs,
|
||||
tick: Date.now()
|
||||
}
|
||||
if (typeof self._procs === 'undefined') {
|
||||
self._bindProcesses()
|
||||
}
|
||||
})
|
||||
socketSys.emit('procs')
|
||||
// watch processes
|
||||
this._socket(conf.NSP.PROCESS)
|
||||
.on(conf.SOCKET_EVENTS.DATA_PROCESSES, function (procs) {
|
||||
self._data.processes = {
|
||||
data: procs,
|
||||
tick: Date.now()
|
||||
}
|
||||
self._processesTable()
|
||||
})
|
||||
.emit(conf.SOCKET_EVENTS.PULL_PROCESSES)
|
||||
.on(conf.SOCKET_EVENTS.DATA_USAGE, function (proc) {
|
||||
if (!self._data.usages || proc.pid !== self._data.usages.pid || self._data.usages.time === proc.time) {
|
||||
return
|
||||
}
|
||||
self._data.usages.time = proc.time
|
||||
self._data.usages.cpu.shift()
|
||||
self._data.usages.cpu.push(Math.min(100, Math.max(proc.usage.cpu, 1)))
|
||||
self._data.usages.mem.shift()
|
||||
self._data.usages.mem.push(Math.min(100, Math.max(proc.usage.memory, 1)))
|
||||
})
|
||||
|
||||
this._socket(conf.NSP.PROC).on('proc', function (proc) {
|
||||
if (!self._usages || proc.pid !== self._usages.pid || self._usages.time === proc.time) {
|
||||
// subscribe logs
|
||||
this._socket(conf.NSP.LOG).on(conf.SOCKET_EVENTS.DATA, function (log) {
|
||||
if (!self._eles.logs || self._data.lastLogPMId !== log.id) {
|
||||
return
|
||||
}
|
||||
self._usages.time = proc.time
|
||||
self._usages.cpu.shift()
|
||||
self._usages.cpu.push(Math.min(100, Math.max(proc.usage.cpu, 1)))
|
||||
self._usages.mem.shift()
|
||||
self._usages.mem.push(Math.min(100, Math.max(proc.usage.memory, 1)))
|
||||
})
|
||||
|
||||
this._socket(conf.NSP.LOG).on('log', function (log) {
|
||||
if (!self._eles.logs || self._lastLogPMId !== log.pm_id) {
|
||||
return
|
||||
}
|
||||
self._eles.logs.log(log.msg)
|
||||
self._eles.logs.log(log.text)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Bind processes to table.
|
||||
* Render processes in a datatable
|
||||
* @return {N/A}
|
||||
*/
|
||||
Layout.prototype._bindProcesses = function () {
|
||||
if (exiting || !this._eles.processes || !this._procs) {
|
||||
Layout.prototype._processesTable = function () {
|
||||
if (this._data.exiting || !this._eles.processes || !this._data.processes) {
|
||||
return
|
||||
}
|
||||
if (this._procs.tick === this._procsLastTick) {
|
||||
if (this._data.processes.tick === this._data.processesLastTick) {
|
||||
// Update tick only.
|
||||
return setRows.call(this, true)
|
||||
return this._processesTableRows(true)
|
||||
}
|
||||
|
||||
if (typeof this._procsLastTick === 'undefined') {
|
||||
if (_.isUndefined(this._data.processesLastTick)) {
|
||||
// show first process informations.
|
||||
this._describeInfo(0)
|
||||
this._eles.processes.rows.on('select', onSelect.bind(this))
|
||||
// bind `select` event on datatable.
|
||||
this._eles.processes.rows.on('select', this._onProcessesTableSelect.bind(this))
|
||||
}
|
||||
// cache last tick
|
||||
this._data.processesLastTick = this._data.processes.tick
|
||||
// render rows of datatable
|
||||
this._processesTableRows(true)
|
||||
}
|
||||
|
||||
this._procsLastTick = this._procs.tick
|
||||
/**
|
||||
* Render processes datatable rows
|
||||
* @param {Boolean} forceRefresh
|
||||
* @return {N/A}
|
||||
*/
|
||||
Layout.prototype._processesTableRows = function (forceRefresh) {
|
||||
var rows = []
|
||||
var selectedIndex = this._eles.processes.rows.selected
|
||||
var len = this._data.processes.data.length
|
||||
|
||||
setRows.call(this, true)
|
||||
this._data.processes.data.forEach(function (p, i) {
|
||||
var pm2 = p.pm2_env
|
||||
var index = '[' + (i + 1) + '/' + len + ']'
|
||||
rows.push([
|
||||
' ' + chalk.grey((index + Array(8 - index.length).join(' '))) + ' ' + p.name,
|
||||
pm2.restart_time,
|
||||
pm2.status !== 'online' ? '0s' : _fromNow(Math.ceil((Date.now() - pm2.pm_uptime) / 1000), true),
|
||||
pm2.status === 'online' ? chalk.green('✔') : chalk.red('✘')
|
||||
])
|
||||
})
|
||||
this._eles.processes.setData({
|
||||
headers: [' Name', 'Restarts', 'Uptime', ''],
|
||||
rows: rows
|
||||
})
|
||||
|
||||
function setRows (forceRefresh) {
|
||||
var rows = []
|
||||
var selectedIndex = this._eles.processes.rows.selected
|
||||
var len = this._procs.data.length
|
||||
selectedIndex = !_.isUndefined(selectedIndex) ? selectedIndex : 0
|
||||
var maxIndex = this._eles.processes.rows.items.length - 1
|
||||
if (selectedIndex > maxIndex) {
|
||||
selectedIndex = maxIndex
|
||||
}
|
||||
this._eles.processes.rows.select(selectedIndex)
|
||||
|
||||
this._procs.data.forEach(function (p, i) {
|
||||
var pm2 = p.pm2_env
|
||||
var index = '[' + i + '/' + len + ']'
|
||||
rows.push([
|
||||
' ' + chalk.grey((index + Array(8 - index.length).join(' '))) + ' ' + p.name,
|
||||
pm2.restart_time,
|
||||
pm2.status !== 'online' ? '0s' : _fromNow(Math.ceil((Date.now() - pm2.pm_uptime) / 1000), true),
|
||||
pm2.status === 'online' ? chalk.green('✔') : chalk.red('✘')
|
||||
])
|
||||
})
|
||||
this._eles.processes.setData({
|
||||
headers: [' Name', 'Restarts', 'Uptime', ''],
|
||||
rows: rows
|
||||
})
|
||||
if (forceRefresh) {
|
||||
this._onProcessesTableSelect()
|
||||
}
|
||||
}
|
||||
|
||||
selectedIndex = typeof selectedIndex !== 'undefined' ? selectedIndex : 0
|
||||
var maxIndex = this._eles.processes.rows.items.length - 1
|
||||
if (selectedIndex > maxIndex) {
|
||||
selectedIndex = maxIndex
|
||||
}
|
||||
this._eles.processes.rows.select(selectedIndex)
|
||||
|
||||
if (forceRefresh) {
|
||||
onSelect.call(this)
|
||||
/**
|
||||
* Listening select event on processes datatable.
|
||||
* @param {Object} item
|
||||
* @param {Number} selectedIndex
|
||||
* @return {N/A}
|
||||
*/
|
||||
Layout.prototype._onProcessesTableSelect = function (item, selectedIndex) {
|
||||
if (!!item) { // eslint-disable-line no-extra-boolean-cast
|
||||
var lastIndex = this._data.lastSelectedIndex
|
||||
this._data.lastSelectedIndex = selectedIndex
|
||||
if (selectedIndex !== lastIndex) {
|
||||
this._describeInfo(selectedIndex)
|
||||
}
|
||||
}
|
||||
|
||||
function onSelect (item, selectedIndex) {
|
||||
if (!!item) { // eslint-disable-line no-extra-boolean-cast
|
||||
var lastIndex = this._lastSelectedIndex
|
||||
|
||||
this._lastSelectedIndex = selectedIndex
|
||||
if (selectedIndex !== lastIndex) {
|
||||
this._describeInfo(selectedIndex)
|
||||
}
|
||||
}
|
||||
this._cpuAndMemUsage(this._lastSelectedIndex || 0)
|
||||
this._displayLogs(this._lastSelectedIndex || 0)
|
||||
this.screen.render()
|
||||
}
|
||||
this._cpuAndMemUsage(this._data.lastSelectedIndex || 0)
|
||||
this._displayLogs(this._data.lastSelectedIndex || 0)
|
||||
this._eles.screen.render()
|
||||
}
|
||||
|
||||
/**
|
||||
* Get description of a specified process.
|
||||
* @param {Number} index the selected row index.
|
||||
* @return {N/A}
|
||||
*/
|
||||
Layout.prototype._describeInfo = function (index) {
|
||||
var pm2 = this._dataOf(index)
|
||||
|
|
@ -199,7 +223,9 @@ Layout.prototype._describeInfo = function (index) {
|
|||
}
|
||||
if (pm2.pm2_env && pm2.pm2_env.env) {
|
||||
// Remove useless large-bytes attributes.
|
||||
delete pm2.pm2_env.env['LS_COLORS']
|
||||
ignoredENVKeys.forEach(function (envKey) {
|
||||
delete pm2.pm2_env.env[envKey]
|
||||
})
|
||||
}
|
||||
delete pm2.monit
|
||||
this._eles.json.setContent(_formatJSON(pm2))
|
||||
|
|
@ -208,60 +234,63 @@ Layout.prototype._describeInfo = function (index) {
|
|||
/**
|
||||
* CPU and Memory usage of a specific process
|
||||
* @param {Number} index the selected row index.
|
||||
* @return {N/A}
|
||||
*/
|
||||
Layout.prototype._cpuAndMemUsage = function (index) {
|
||||
var pm2 = this._dataOf(index)
|
||||
if (!pm2) {
|
||||
return
|
||||
}
|
||||
if (!this._usages) {
|
||||
this._usages = {
|
||||
if (!this._data.usages) {
|
||||
this._data.usages = {
|
||||
mem: [],
|
||||
cpu: []
|
||||
}
|
||||
var len = this._eles.cpu.width - 4
|
||||
for (var i = 0; i < len; i++) {
|
||||
this._usages.cpu.push(1)
|
||||
this._usages.mem.push(1)
|
||||
this._data.usages.cpu.push(1)
|
||||
this._data.usages.mem.push(1)
|
||||
}
|
||||
}
|
||||
if (pm2.pid !== 0 && this._procCount === 2) {
|
||||
this._procCount = -1
|
||||
this._socket(conf.NSP.PROC).emit('proc', pm2.pid)
|
||||
// fetch process info every 3 times
|
||||
if (pm2.pid !== 0 && this._data.processCount === 2) {
|
||||
this._data.processCount = -1
|
||||
this._socket(conf.NSP.PROCESS).emit(conf.SOCKET_EVENTS.PULL_USAGE, pm2.pid)
|
||||
}
|
||||
this._procCount++
|
||||
this._usages.pid = pm2.pid
|
||||
this._data.processCount++
|
||||
this._data.usages.pid = pm2.pid
|
||||
|
||||
this._eles.cpu.setData(this._usages.cpu, 0, 100)
|
||||
this._eles.cpu.setLabel('CPU Usage (' + (this._usages.cpu[this._usages.cpu.length - 1]).toFixed(2) + '%)')
|
||||
this._eles.cpu.setData(this._data.usages.cpu, 0, 100)
|
||||
this._eles.cpu.setLabel('CPU Usage (' + (this._data.usages.cpu[this._data.usages.cpu.length - 1]).toFixed(2) + '%)')
|
||||
|
||||
this._eles.mem.setData(this._usages.mem, 0, 100)
|
||||
this._eles.mem.setLabel('Memory Usage (' + (this._usages.mem[this._usages.mem.length - 1]).toFixed(2) + '%)')
|
||||
this._eles.mem.setData(this._data.usages.mem, 0, 100)
|
||||
this._eles.mem.setLabel('Memory Usage (' + (this._data.usages.mem[this._data.usages.mem.length - 1]).toFixed(2) + '%)')
|
||||
}
|
||||
|
||||
/**
|
||||
* Display logs.
|
||||
* @param {Number} index [description]
|
||||
* @return {[type]} [description]
|
||||
* @param {Number} index
|
||||
* @return {N/A}
|
||||
*/
|
||||
Layout.prototype._displayLogs = function (index) {
|
||||
var pm2 = this._dataOf(index)
|
||||
if (!pm2 || this._lastLogPMId === pm2.pm_id) {
|
||||
if (!pm2 || this._data.lastLogPMId === pm2.pm_id) {
|
||||
return
|
||||
}
|
||||
this._killLogs()
|
||||
this._socket(conf.NSP.LOG).emit('tail', this._lastLogPMId = pm2.pm_id, true)
|
||||
this._stopLogging()
|
||||
this._socket(conf.NSP.LOG).emit(conf.SOCKET_EVENTS.PULL_LOGS, pm2.pm_id, true)
|
||||
this._data.lastLogPMId = pm2.pm_id
|
||||
}
|
||||
|
||||
/**
|
||||
* Kill `tail` process
|
||||
* @return {[type]} [description]
|
||||
* Stop logging.
|
||||
* @return {N/A}
|
||||
*/
|
||||
Layout.prototype._killLogs = function () {
|
||||
if (typeof this._lastLogPMId === 'undefined') {
|
||||
Layout.prototype._stopLogging = function () {
|
||||
if (_.isUndefined(this._data.lastLogPMId)) {
|
||||
return
|
||||
}
|
||||
this._socket(conf.NSP.LOG).emit('tail_kill', this._lastLogPMId)
|
||||
this._socket(conf.NSP.LOG).emit(conf.SOCKET_EVENTS.PULL_LOGS_END, this._data.lastLogPMId)
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -270,14 +299,15 @@ Layout.prototype._killLogs = function () {
|
|||
* @return {Object}
|
||||
*/
|
||||
Layout.prototype._dataOf = function (index) {
|
||||
if (!this._procs || !Array.isArray(this._procs.data) || index >= this._procs.data.length) {
|
||||
if (!this._data.processes || !Array.isArray(this._data.processes.data) || index >= this._data.processes.data.length) {
|
||||
return null
|
||||
}
|
||||
return this._procs.data[index]
|
||||
return this._data.processes.data[index]
|
||||
}
|
||||
|
||||
/**
|
||||
* Draw elements.
|
||||
* @return {N/A}
|
||||
*/
|
||||
Layout.prototype._draw = function () {
|
||||
console.info('Rendering dashboard...')
|
||||
|
|
@ -289,21 +319,20 @@ Layout.prototype._draw = function () {
|
|||
|
||||
// Processes.
|
||||
this._eles.processes = grid.get(0, 0)
|
||||
this._bindProcesses()
|
||||
this._processesTable()
|
||||
|
||||
this._eles.cpu = grid.get(1, 0)
|
||||
this._eles.mem = grid.get(1, 1)
|
||||
_.extend(this._eles, {
|
||||
cpu: grid.get(1, 0),
|
||||
mem: grid.get(1, 1),
|
||||
logs: grid.get(2, 0),
|
||||
json: grid.get(0, 2)
|
||||
})
|
||||
|
||||
// Logs.
|
||||
this._eles.logs = grid.get(2, 0)
|
||||
|
||||
// Detail.
|
||||
this._eles.json = grid.get(0, 2)
|
||||
var offset = Math.round(this._eles.json.height * 100 / this._eles.json.getScrollHeight())
|
||||
var dir
|
||||
// Key bindings
|
||||
screen.key('s', function (ch, key) {
|
||||
if (exiting) {
|
||||
if (self._data.exiting) {
|
||||
return
|
||||
}
|
||||
var perc = Math.min((dir !== 'down' ? offset : 0) + self._eles.json.getScrollPerc() + 5, 100)
|
||||
|
|
@ -311,20 +340,19 @@ Layout.prototype._draw = function () {
|
|||
self._eles.json.setScrollPerc(perc)
|
||||
})
|
||||
screen.key('w', function (ch, key) {
|
||||
if (exiting) {
|
||||
if (self._data.exiting) {
|
||||
return
|
||||
}
|
||||
var perc = Math.max(self._eles.json.getScrollPerc() - 5 - (dir !== 'up' ? offset : 0), 0)
|
||||
dir = 'up'
|
||||
self._eles.json.setScrollPerc(perc)
|
||||
})
|
||||
|
||||
screen.key(['escape', 'q', 'C-c'], function (ch, key) {
|
||||
if (exiting) {
|
||||
if (self._data.exiting) {
|
||||
return
|
||||
}
|
||||
exiting = true
|
||||
this._killLogs()
|
||||
self._data.exiting = true
|
||||
this._stopLogging()
|
||||
screen.title = 'PM2 Monitor (Exiting...)'
|
||||
screen.destroy()
|
||||
screen.title = ''
|
||||
|
|
@ -337,16 +365,17 @@ Layout.prototype._draw = function () {
|
|||
}.bind(this))
|
||||
|
||||
screen.render()
|
||||
this.screen = screen
|
||||
this._eles.screen = screen
|
||||
}
|
||||
|
||||
/**
|
||||
* Get socket.io object by namespace
|
||||
* @param {String} ns
|
||||
* @return {socket.io}
|
||||
*/
|
||||
Layout.prototype._socket = function (ns) {
|
||||
if (ns && this.sockets) {
|
||||
return this.sockets[(ns || '').replace(/^\/+/g, '').toLowerCase()]
|
||||
if (ns && this._data.sockets) {
|
||||
return this._data.sockets[(ns || '').replace(/^\/+/g, '').toLowerCase()]
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
|
@ -480,9 +509,9 @@ function _grid (screen) {
|
|||
* @private
|
||||
*/
|
||||
function _formatJSON (data) {
|
||||
data = JSON.stringify(typeof data !== 'string' ? data : JSON.parse(data), null, 2)
|
||||
data = JSON.stringify(!_.isString(data) ? data : JSON.parse(data), null, 2)
|
||||
|
||||
return data.replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g, function (m) {
|
||||
return data.replace(regJSON, function (m) {
|
||||
var color = 'blue'
|
||||
if (/^"/.test(m)) {
|
||||
color = ['magenta', 'green'][/:$/.test(m) ? 0 : 1]
|
||||
|
|
|
|||
|
|
@ -1,9 +1,13 @@
|
|||
'use strict'
|
||||
|
||||
// Inspired by the blessed-contrib, but more powerful and free.
|
||||
// (c) Tjatse
|
||||
|
||||
var blessed = require('blessed')
|
||||
var _ = require('lodash')
|
||||
var util = require('util')
|
||||
var re_stripANSI = /(?:(?:\u001b\[)|\u009b)(?:(?:[0-9]{1,3})?(?:(?:;[0-9]{0,3})*)?[A-M|f-m])|\u001b[A-M]/g
|
||||
|
||||
var regStripANSI = /(?:(?:\u001b\[)|\u009b)(?:(?:[0-9]{1,3})?(?:(?:;[0-9]{0,3})*)?[A-M|f-m])|\u001b[A-M]/g
|
||||
|
||||
exports.Grid = Grid
|
||||
exports.Table = Table
|
||||
|
|
@ -14,13 +18,12 @@ exports.Log = Log
|
|||
* Grid cells.
|
||||
* @param {Object} options
|
||||
* @returns {Grid}
|
||||
* @constructor
|
||||
*/
|
||||
function Grid (options) {
|
||||
if (!(this instanceof Grid)) {
|
||||
return new Grid(options)
|
||||
}
|
||||
options = util._extend({
|
||||
options = _.extend({
|
||||
margin: 2
|
||||
}, options || {})
|
||||
|
||||
|
|
@ -55,7 +58,7 @@ Grid.prototype.set = function (ele) {
|
|||
}
|
||||
return
|
||||
}
|
||||
this.grids[ele.row][ele.col] = util._extend({rowSpan: 1, colSpan: 1}, ele)
|
||||
this.grids[ele.row][ele.col] = _.extend({rowSpan: 1, colSpan: 1}, ele)
|
||||
}
|
||||
/**
|
||||
* Draw grid.
|
||||
|
|
@ -109,7 +112,7 @@ Grid.prototype.draw = function (screen, rect) {
|
|||
left: left
|
||||
})
|
||||
} else {
|
||||
screen.append(ele.instance = ele.element(util._extend(ele.options || {}, {
|
||||
screen.append(ele.instance = ele.element(_.extend(ele.options || {}, {
|
||||
top: top + '%',
|
||||
left: left + '%',
|
||||
width: width + '%',
|
||||
|
|
@ -136,7 +139,7 @@ function Table (options) {
|
|||
|
||||
blessed.Box.call(this, this.options)
|
||||
|
||||
this.rows = blessed.list(util._extend(this.options.rows || {}, {
|
||||
this.rows = blessed.list(_.extend(this.options.rows || {}, {
|
||||
height: 0,
|
||||
top: 1,
|
||||
width: 0,
|
||||
|
|
@ -175,7 +178,7 @@ Table.prototype.setData = function (data) {
|
|||
var dataToString = function (d) {
|
||||
return d.map(function (s, i) {
|
||||
s = s.toString()
|
||||
var s1 = s.replace(re_stripANSI, '')
|
||||
var s1 = s.replace(regStripANSI, '')
|
||||
var size = !def ? widths : widths[i]
|
||||
var len = size - s1.length
|
||||
|
||||
|
|
@ -208,7 +211,7 @@ function Sparkline (options) {
|
|||
return new Sparkline(options)
|
||||
}
|
||||
|
||||
this.options = util._extend({
|
||||
this.options = _.extend({
|
||||
chars: ['▂', '▃', '▄', '▅', '▆', '▇', '█'],
|
||||
tags: true,
|
||||
padding: {
|
||||
|
|
|
|||
Loading…
Reference in New Issue