X-Git-Url: http://www.aleph1.co.uk/gitweb/?p=yaffs-website;a=blobdiff_plain;f=node_modules%2Fprogress%2Flib%2Fnode-progress.js;fp=node_modules%2Fprogress%2Flib%2Fnode-progress.js;h=0f47a9f48ae340a80f2af06a3843c574f349b26d;hp=0000000000000000000000000000000000000000;hb=a2bd1bf0c2c1f1a17d188f4dc0726a45494cefae;hpb=57c063afa3f66b07c4bbddc2d6129a96d90f0aad diff --git a/node_modules/progress/lib/node-progress.js b/node_modules/progress/lib/node-progress.js new file mode 100644 index 000000000..0f47a9f48 --- /dev/null +++ b/node_modules/progress/lib/node-progress.js @@ -0,0 +1,180 @@ +/*! + * node-progress + * Copyright(c) 2011 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Expose `ProgressBar`. + */ + +exports = module.exports = ProgressBar; + +/** + * Initialize a `ProgressBar` with the given `fmt` string and `options` or + * `total`. + * + * Options: + * + * - `total` total number of ticks to complete + * - `width` the displayed width of the progress bar defaulting to total + * - `stream` the output stream defaulting to stderr + * - `complete` completion character defaulting to "=" + * - `incomplete` incomplete character defaulting to "-" + * - `callback` optional function to call when the progress bar completes + * - `clear` will clear the progress bar upon termination + * + * Tokens: + * + * - `:bar` the progress bar itself + * - `:current` current tick number + * - `:total` total ticks + * - `:elapsed` time elapsed in seconds + * - `:percent` completion percentage + * - `:eta` eta in seconds + * + * @param {string} fmt + * @param {object|number} options or total + * @api public + */ + +function ProgressBar(fmt, options) { + this.stream = options.stream || process.stderr; + + if (typeof(options) == 'number') { + var total = options; + options = {}; + options.total = total; + } else { + options = options || {}; + if ('string' != typeof fmt) throw new Error('format required'); + if ('number' != typeof options.total) throw new Error('total required'); + } + + this.fmt = fmt; + this.curr = 0; + this.total = options.total; + this.width = options.width || this.total; + this.clear = options.clear + this.chars = { + complete : options.complete || '=', + incomplete : options.incomplete || '-' + }; + this.callback = options.callback || function () {}; + this.lastDraw = ''; +} + +/** + * "tick" the progress bar with optional `len` and optional `tokens`. + * + * @param {number|object} len or tokens + * @param {object} tokens + * @api public + */ + +ProgressBar.prototype.tick = function(len, tokens){ + if (len !== 0) + len = len || 1; + + // swap tokens + if ('object' == typeof len) tokens = len, len = 1; + + // start time for eta + if (0 == this.curr) this.start = new Date; + + this.curr += len + this.render(tokens); + + // progress complete + if (this.curr >= this.total) { + this.complete = true; + this.terminate(); + this.callback(this); + return; + } +}; + +/** + * Method to render the progress bar with optional `tokens` to place in the + * progress bar's `fmt` field. + * + * @param {object} tokens + * @api public + */ + +ProgressBar.prototype.render = function (tokens) { + if (!this.stream.isTTY) return; + + var ratio = this.curr / this.total; + ratio = Math.min(Math.max(ratio, 0), 1); + + var percent = ratio * 100; + var incomplete, complete, completeLength; + var elapsed = new Date - this.start; + var eta = (percent == 100) ? 0 : elapsed * (this.total / this.curr - 1); + + /* populate the bar template with percentages and timestamps */ + var str = this.fmt + .replace(':current', this.curr) + .replace(':total', this.total) + .replace(':elapsed', isNaN(elapsed) ? '0.0' : (elapsed / 1000).toFixed(1)) + .replace(':eta', (isNaN(eta) || !isFinite(eta)) ? '0.0' : (eta / 1000) + .toFixed(1)) + .replace(':percent', percent.toFixed(0) + '%'); + + /* compute the available space (non-zero) for the bar */ + var availableSpace = Math.max(0, this.stream.columns - str.replace(':bar', '').length); + var width = Math.min(this.width, availableSpace); + + /* TODO: the following assumes the user has one ':bar' token */ + completeLength = Math.round(width * ratio); + complete = Array(completeLength + 1).join(this.chars.complete); + incomplete = Array(width - completeLength + 1).join(this.chars.incomplete); + + /* fill in the actual progress bar */ + str = str.replace(':bar', complete + incomplete); + + /* replace the extra tokens */ + if (tokens) for (var key in tokens) str = str.replace(':' + key, tokens[key]); + + if (this.lastDraw !== str) { + this.stream.clearLine(); + this.stream.cursorTo(0); + this.stream.write(str); + this.lastDraw = str; + } +}; + +/** + * "update" the progress bar to represent an exact percentage. + * The ratio (between 0 and 1) specified will be multiplied by `total` and + * floored, representing the closest available "tick." For example, if a + * progress bar has a length of 3 and `update(0.5)` is called, the progress + * will be set to 1. + * + * A ratio of 0.5 will attempt to set the progress to halfway. + * + * @param {number} ratio The ratio (between 0 and 1 inclusive) to set the + * overall completion to. + * @api public + */ + +ProgressBar.prototype.update = function (ratio, tokens) { + var goal = Math.floor(ratio * this.total); + var delta = goal - this.curr; + + this.tick(delta, tokens); +}; + +/** + * Terminates a progress bar. + * + * @api public + */ + +ProgressBar.prototype.terminate = function () { + if (this.clear) { + this.stream.clearLine(); + this.stream.cursorTo(0); + } else console.log(); +};