Skip to content

Commit

Permalink
use ansi escapes to render spinner more cleanly
Browse files Browse the repository at this point in the history
  • Loading branch information
Jeff Dickey committed May 20, 2016
1 parent bc2f0c7 commit 9dd6a9c
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 69 deletions.
46 changes: 23 additions & 23 deletions lib/action.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,47 +4,47 @@ let cli = require('..')
let errors = require('./errors')

function action (message, options, promise) {
if (options.then) {
let swap = promise
promise = options
options = swap
}
if (options.then) [options, promise] = [promise, options]
options = options || {}

module.exports.task = {
let task = module.exports.task = {
promise: promise,
spinner: new cli.Spinner({spinner: options.spinner, text: `${message}... `})
}
task.spinner.start()

module.exports.task.spinner.start()
return promise.then(function (result) {
module.exports.task.spinner.stop()
module.exports.task = null
if (options.success !== false) {
cli.console.error(options.success || 'done')
}
if (options.success !== false) done(options.success || 'done')
else done()
return result
}).catch(function (err) {
module.exports.task.spinner.stop()
module.exports.task = null
if (err.body && err.body.id === 'two_factor') {
cli.console.error(cli.color.yellow.bold('!'))
} else {
cli.console.error(cli.color.red.bold('!!!'))
}
if (err.body && err.body.id === 'two_factor') done(cli.color.yellow.bold('!'))
else done(cli.color.red.bold('!!!'))
throw err
})
}

function warn (msg) {
if (module.exports.task) module.exports.task.spinner.warn(msg)
let task = module.exports.task
if (task) task.spinner.warn(msg)
else errors.warn(msg)
}

function update (msg) {
if (module.exports.task) module.exports.task.spinner.update(msg)
function status (status) {
let task = module.exports.task
if (task) task.spinner.status = status
}

function done (msg) {
let task = module.exports.task
if (task) {
task.spinner.stop()
module.exports.task = null
}
if (msg) cli.console.error(msg)
}

module.exports = action
module.exports.warn = warn
module.exports.update = update
module.exports.status = status
module.exports.done = done
86 changes: 41 additions & 45 deletions lib/spinner.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ class Spinner {
text: ''
}, options)

this.cursor = require('cli-cursor')
this.ansi = require('ansi-escapes')
let spinners = require('./spinners.json')

this.color = this.options.color || 'heroku'
Expand All @@ -21,74 +21,70 @@ class Spinner {
this.interval = this.options.interval || this.spinner.interval || 100
this.id = null
this.frameIndex = 0
this.enabled = !console.mocking() && (process.stderr && process.stderr.isTTY) && !process.env.CI
}

frame () {
var frames = this.spinner.frames
var frame = frames[this.frameIndex]
if (this.color) frame = color[this.color](frame)
this.frameIndex = ++this.frameIndex % frames.length
return frame
}

clear () {
if (!this.enabled) {
return
}

process.stderr.clearLine()
process.stderr.cursorTo(0)
}

render () {
process.stderr.write('\b' + this.frame())
this.stream = process.stderr
this.enabled = !console.mocking() && (this.stream && this.stream.isTTY) && !process.env.CI
}

start () {
if (this.id) return
console.writeError(this.text)
if (!this.enabled) return
console.writeError(' ')

this.cursor.hide()
this.render()
this.id = setInterval(this.render.bind(this), this.interval)
this.stream.write(this.ansi.cursorSavePosition)
this.stream.write(this.ansi.cursorHide)
this._render()
this.id = setInterval(this._render.bind(this), this.interval)
}

stop () {
if (!this.enabled) {
return
}
if (!this.enabled) return

clearInterval(this.id)
this.id = null
this.enabled = false
this.frameIndex = 0
this.clear()
process.stderr.write(this.text)
this.cursor.show()
this._render()
this.stream.write(this.ansi.cursorShow)
}

update (text) {
this.text = text
if (!this.enabled) {
console.writeError('\n' + this.text)
} else {
this.clear()
process.stderr.write(this.text + ' ')
}
clear () {
this.stream.write(this.ansi.cursorRestorePosition)
this.stream.write(this.ansi.eraseDown)
}

warn (msg) {
if (this.enabled) {
this.stop()
this.clear()
} else {
console.error(color.yellow.bold('!'))
}
} else console.error(color.yellow.bold('!'))

errors.warn(msg)
this.start()
}

get status () {
return this._status
}

set status (status) {
this._status = status
if (!this.enabled) this.stream.write(`${this.text}${this.status}\n`)
}

_render () {
this.clear()
this.stream.write(this.text)
if (this.enabled) this.stream.write(' ' + this._frame())
if (this.status) this.stream.write(' ' + this.status)
this.stream.write('\n')
}

_frame () {
var frames = this.spinner.frames
var frame = frames[this.frameIndex]
if (this.color) frame = color[this.color](frame)
this.frameIndex = ++this.frameIndex % frames.length
return frame
}
}

module.exports = Spinner
1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
"dependencies": {
"cardinal": "^0.7.1",
"chalk": "^1.1.3",
"cli-cursor": "^1.0.2",
"co": "^4.6.0",
"got": "^6.3.0",
"heroku-client": "3.0.0-alpha3",
Expand Down

0 comments on commit 9dd6a9c

Please sign in to comment.