diff options
author | isaacs <i@izs.me> | 2014-05-08 02:17:26 +0400 |
---|---|---|
committer | isaacs <i@izs.me> | 2014-05-08 02:18:38 +0400 |
commit | bf761dddd14ce07b7070a38ec0661d4a21e7577f (patch) | |
tree | 3e78912ffb5be5c51caa8feee99ef1d34f39c85f | |
parent | 7fc87498678ecd602f5f5c37cc930a61670af264 (diff) |
Busy Spinner, no http noise
One step closer to #5213
-rw-r--r-- | doc/misc/npm-config.md | 11 | ||||
-rw-r--r-- | lib/help.js | 1 | ||||
-rw-r--r-- | lib/init.js | 1 | ||||
-rw-r--r-- | lib/npm.js | 18 | ||||
-rw-r--r-- | lib/utils/lifecycle.js | 3 | ||||
-rw-r--r-- | lib/version.js | 5 | ||||
-rw-r--r-- | lib/view.js | 2 | ||||
-rw-r--r-- | node_modules/char-spinner/LICENSE | 15 | ||||
-rw-r--r-- | node_modules/char-spinner/README.md | 31 | ||||
-rw-r--r-- | node_modules/char-spinner/package.json | 40 | ||||
-rw-r--r-- | node_modules/char-spinner/spin.js | 41 | ||||
-rw-r--r-- | node_modules/char-spinner/test/basic.js | 35 | ||||
-rw-r--r-- | package.json | 2 |
13 files changed, 204 insertions, 1 deletions
diff --git a/doc/misc/npm-config.md b/doc/misc/npm-config.md index a70de8121..4792d808f 100644 --- a/doc/misc/npm-config.md +++ b/doc/misc/npm-config.md @@ -712,6 +712,17 @@ using `-s` to add a signature. Note that git requires you to have set up GPG keys in your git configs for this to work properly. +### spin + +* Default: true +* Type: Boolean or `"always"` + +When set to `true`, npm will display an ascii spinner while it is doing +things, if `process.stderr` is a TTY. + +Set to `false` to suppress the spinner, or set to `always` to output +the spinner even for non-TTY outputs. + ### strict-ssl * Default: true diff --git a/lib/help.js b/lib/help.js index 72b4393b6..c68f322ab 100644 --- a/lib/help.js +++ b/lib/help.js @@ -15,6 +15,7 @@ var fs = require("graceful-fs") , glob = require("glob") function help (args, cb) { + npm.spinner.stop() var argv = npm.config.get("argv").cooked var argnum = 0 diff --git a/lib/init.js b/lib/init.js index d064ae8bc..74cd806f6 100644 --- a/lib/init.js +++ b/lib/init.js @@ -12,6 +12,7 @@ init.usage = "npm init" function init (args, cb) { var dir = process.cwd() log.pause() + npm.spinner.stop() var initFile = npm.config.get('init-module') console.log( diff --git a/lib/npm.js b/lib/npm.js index 613bf0095..44c132f2c 100644 --- a/lib/npm.js +++ b/lib/npm.js @@ -30,6 +30,7 @@ var EventEmitter = require("events").EventEmitter , slide = require("slide") , chain = slide.chain , RegClient = require("npm-registry-client") + , charSpin = require("char-spinner") npm.config = { loaded: false, @@ -182,6 +183,21 @@ var commandCache = {} }) , abbrevs = abbrev(fullList) +npm.spinner = + { int: null + , start: function () { + if (npm.spinner.int) return + var c = npm.config.get("spin") + if (!c) return + var stream = npm.config.get("logstream") + var opt = { tty: c !== "always", stream: stream } + npm.spinner.int = charSpin(opt) + } + , stop: function () { + clearInterval(npm.spinner.int) + } + } + Object.keys(abbrevs).concat(plumbing).forEach(function addCommand (c) { Object.defineProperty(npm.commands, c, { get : function () { if (!loaded) throw new Error( @@ -204,6 +220,8 @@ Object.keys(abbrevs).concat(plumbing).forEach(function addCommand (c) { } if (args.length === 1) args.unshift([]) + npm.spinner.start() + if (!npm.registry.refer) { npm.registry.refer = [a].concat(args[0]).map(function (arg) { // exclude anything that might be a URL, path, or private module diff --git a/lib/utils/lifecycle.js b/lib/utils/lifecycle.js index 1af5bddca..af009cc21 100644 --- a/lib/utils/lifecycle.js +++ b/lib/utils/lifecycle.js @@ -162,6 +162,9 @@ function runCmd (note, cmd, pkg, env, stage, wd, unsafe, cb) { , group = unsafe ? null : npm.config.get("group") if (log.level !== 'silent') { + if (npm.spinner.int) { + npm.config.get("logstream").write("\r \r") + } console.log(note) } log.verbose("unsafe-perm in lifecycle", unsafe) diff --git a/lib/version.js b/lib/version.js index bc4871592..ec3f93b20 100644 --- a/lib/version.js +++ b/lib/version.js @@ -105,6 +105,11 @@ function checkGit (data, cb) { chain ( [ [ exec, git, [ "add", "package.json" ], {env: process.env} ] , [ exec, git, [ "commit", "-m", message ], {env: process.env} ] + , sign && function (cb) { + npm.spinner.stop() + cb() + } + , [ exec, git, [ "tag", "v" + data.version, flag, message ] , {env: process.env} ] ] , cb ) diff --git a/lib/view.js b/lib/view.js index 18484b2bd..6b7382378 100644 --- a/lib/view.js +++ b/lib/view.js @@ -208,7 +208,7 @@ function printData (data, name, cb) { d = JSON.stringify(d) } if (f && showFields) f += " = " - if (d.indexOf("\n") !== -1) d = "\n" + d + if (d.indexOf("\n") !== -1) d = " \n" + d msg += (showVersions ? name + "@" + v + " " : "") + (showFields ? f : "") + d + "\n" }) diff --git a/node_modules/char-spinner/LICENSE b/node_modules/char-spinner/LICENSE new file mode 100644 index 000000000..05eeeb88c --- /dev/null +++ b/node_modules/char-spinner/LICENSE @@ -0,0 +1,15 @@ +The ISC License + +Copyright (c) Isaac Z. Schlueter + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/node_modules/char-spinner/README.md b/node_modules/char-spinner/README.md new file mode 100644 index 000000000..b202f4cdd --- /dev/null +++ b/node_modules/char-spinner/README.md @@ -0,0 +1,31 @@ +# char-spinner + +Put a little spinner on process.stderr, as unobtrusively as possible. + +## USAGE + +```javascript +var spinner = require("spinner") + +// All options are optional +// even the options argument itself is optional +spinner(options) +``` + +## OPTIONS + +Usually the defaults are what you want. Mostly they're just +configurable for testing purposes. + +* `stream` Output stream. Default=`process.stderr` +* `tty` Only show spinner if output stream has a truish `.isTTY`. Default=`true` +* `string` String of chars to spin. Default=`'/-\\|'` +* `interval` Number of ms between frames, bigger = slower. Default=`50` +* `cleanup` Print `'\r \r'` to stream on process exit. Default=`true` +* `unref` Unreference the spinner interval so that the process can + exit normally. Default=`true` +* `delay` Number of frames to "skip over" before printing the spinner. + Useful if you want to avoid showing the spinner for very fast + actions. Default=`2` + +Returns the generated interval, if one was created. diff --git a/node_modules/char-spinner/package.json b/node_modules/char-spinner/package.json new file mode 100644 index 000000000..b2760afa6 --- /dev/null +++ b/node_modules/char-spinner/package.json @@ -0,0 +1,40 @@ +{ + "name": "char-spinner", + "version": "1.0.0", + "description": "Put a little spinner on process.stderr, as unobtrusively as possible.", + "main": "spin.js", + "directories": { + "test": "test" + }, + "dependencies": {}, + "devDependencies": { + "tap": "^0.4.10" + }, + "scripts": { + "test": "tap test/*.js" + }, + "repository": { + "type": "git", + "url": "git://github.com/isaacs/char-spinner" + }, + "keywords": [ + "char", + "spinner" + ], + "author": { + "name": "Isaac Z. Schlueter", + "email": "i@izs.me", + "url": "http://blog.izs.me/" + }, + "license": "ISC", + "bugs": { + "url": "https://github.com/isaacs/char-spinner/issues" + }, + "homepage": "https://github.com/isaacs/char-spinner", + "readme": "# char-spinner\n\nPut a little spinner on process.stderr, as unobtrusively as possible.\n\n## USAGE\n\n```javascript\nvar spinner = require(\"spinner\")\n\n// All options are optional\n// even the options argument itself is optional\nspinner(options)\n```\n\n## OPTIONS\n\nUsually the defaults are what you want. Mostly they're just\nconfigurable for testing purposes.\n\n* `stream` Output stream. Default=`process.stderr`\n* `tty` Only show spinner if output stream has a truish `.isTTY`. Default=`true`\n* `string` String of chars to spin. Default=`'/-\\\\|'`\n* `interval` Number of ms between frames, bigger = slower. Default=`50`\n* `cleanup` Print `'\\r \\r'` to stream on process exit. Default=`true`\n* `unref` Unreference the spinner interval so that the process can\n exit normally. Default=`true`\n* `delay` Number of frames to \"skip over\" before printing the spinner.\n Useful if you want to avoid showing the spinner for very fast\n actions. Default=`2`\n\nReturns the generated interval, if one was created.\n", + "readmeFilename": "README.md", + "_id": "char-spinner@1.0.0", + "_shasum": "b5fadba903f242a31c1e93b2f532482d62bb56b2", + "_from": "char-spinner@latest", + "_resolved": "https://registry.npmjs.org/char-spinner/-/char-spinner-1.0.0.tgz" +} diff --git a/node_modules/char-spinner/spin.js b/node_modules/char-spinner/spin.js new file mode 100644 index 000000000..1068d3253 --- /dev/null +++ b/node_modules/char-spinner/spin.js @@ -0,0 +1,41 @@ +module.exports = spinner + +function spinner(opt) { + opt = opt || {} + var str = opt.stream || process.stderr + var tty = typeof opt.tty === 'boolean' ? opt.tty : true + var string = opt.string || '/-\\|' + var ms = typeof opt.interval === 'number' ? opt.interval : 50 + if (ms < 0) ms = 0 + if (tty && !str.isTTY) return false + + var s = 0 + var sprite = string.split('') + var wrote = false + + var delay = typeof opt.delay === 'number' ? opt.delay : 2 + + var interval = setInterval(function() { + if (--delay >= 0) return + s = ++s % sprite.length + var c = sprite[s] + str.write('\r \r' + c + '\r') + wrote = true + }, ms) + + var unref = typeof opt.unref === 'boolean' ? opt.unref : true + if (unref && typeof interval.unref === 'function') { + interval.unref() + } + + var cleanup = typeof opt.cleanup === 'boolean' ? opt.cleanup : true + if (cleanup) { + process.on('exit', function() { + if (wrote) { + str.write('\r \r') + } + }) + } + + return interval +} diff --git a/node_modules/char-spinner/test/basic.js b/node_modules/char-spinner/test/basic.js new file mode 100644 index 000000000..f3c1dfe2b --- /dev/null +++ b/node_modules/char-spinner/test/basic.js @@ -0,0 +1,35 @@ +var test = require('tap').test +var spinner = require('../spin.js') + +test('does nothing when not a tty', function(t) { + var int = spinner({ + stream: { write: function(c) { + throw new Error('wrote something: ' + JSON.stringify(c)) + }, isTTY: false }, + }) + t.notOk(int) + t.end() +}) + +test('write spinny stuff', function(t) { + var output = '' + var written = 0 + var expect = "\r \rb\r\r \rc\r\r \rd\r\r \re\r\r \rf\r\r \rg\r\r \rh\r\r \ri\r\r \rj\r\r \rk\r\r \rl\r\r \rm\r\r \rn\r\r \ro\r\r \rp\r\r \ra\r\r \rb\r\r \rc\r\r \rd\r\r \re\r\r \rf\r\r \rg\r\r \rh\r\r \ri\r\r \rj\r\r \rk\r\r \rl\r\r \rm\r\r \rn\r\r \ro\r\r \rp\r\r \ra\r\r \rb\r\r \rc\r\r \rd\r\r \re\r\r \rf\r\r \rg\r\r \rh\r\r \ri\r\r \rj\r\r \rk\r\r \rl\r\r \rm\r\r \rn\r\r \ro\r\r \rp\r\r \ra\r\r \rb\r\r \rc\r" + + var int = spinner({ + interval: 0, + string: 'abcdefghijklmnop', + stream: { + write: function(c) { + output += c + if (++written == 50) { + t.equal(output, expect) + clearInterval(int) + t.end() + } + }, + isTTY: true + }, + cleanup: false + }) +}) diff --git a/package.json b/package.json index 31511a141..051a2afe1 100644 --- a/package.json +++ b/package.json @@ -40,6 +40,7 @@ "ansistyles": "~0.1.3", "archy": "0", "block-stream": "0.0.7", + "char-spinner": "~1.0.0", "child-process-close": "~0.1.1", "chmodr": "~0.1.0", "chownr": "0", @@ -91,6 +92,7 @@ "ansistyles", "archy", "block-stream", + "char-spinner", "child-process-close", "chmodr", "chownr", |