diff options
author | isaacs <i@izs.me> | 2012-06-17 08:46:16 +0400 |
---|---|---|
committer | isaacs <i@izs.me> | 2012-06-17 08:46:16 +0400 |
commit | d3d325803ed3eda4c626ba9486270999352bee05 (patch) | |
tree | 4629fd2ecbec7b80a39c13d64567b1e941e0dbba /node_modules/read | |
parent | 628d8202fe00283804df90e0345e7dd488297514 (diff) |
update read to 0.1.0
Diffstat (limited to 'node_modules/read')
-rw-r--r-- | node_modules/read/README.md | 7 | ||||
-rw-r--r-- | node_modules/read/example/example.js | 18 | ||||
-rw-r--r-- | node_modules/read/lib/read.js | 59 | ||||
-rw-r--r-- | node_modules/read/package.json | 17 | ||||
-rw-r--r-- | node_modules/read/test/basic.js | 54 |
5 files changed, 119 insertions, 36 deletions
diff --git a/node_modules/read/README.md b/node_modules/read/README.md index 9913b4df0..0c90e1445 100644 --- a/node_modules/read/README.md +++ b/node_modules/read/README.md @@ -18,14 +18,13 @@ Every option is optional. * `prompt` What to write to stdout before reading input. * `silent` Don't echo the output as the user types it. * `num` Max number of chars to read from terminal. -* `delim` The char that means we're done. Default: `"\n"` * `timeout` Number of ms to wait for user input before giving up. * `default` The default value if the user enters nothing. -If silent is true, or num is set, or delim is something other than -`"\n"`, then read will set raw mode, and read character by character. +If silent is true, or num is set, and the input is a TTY, +then read will set raw mode, and read character by character. -At this time, backspace and arrow keys are not supported in raw mode. +At this time, backspace and arrow keys are not supported very well. It's probably not too hard to add support for this, perhaps using node's built-in readline module. diff --git a/node_modules/read/example/example.js b/node_modules/read/example/example.js new file mode 100644 index 000000000..6800dff65 --- /dev/null +++ b/node_modules/read/example/example.js @@ -0,0 +1,18 @@ +var read = require("../lib/read.js") + +read({prompt: "Username: ", default: "test-user" }, function (er, user) { + read({prompt: "Password: ", default: "test-pass", silent: true }, function (er, pass) { + read({prompt: "Enter 4 characters: ", num: 4 }, function (er, four) { + read({prompt: "Password again: ", default: "test-pass", silent: true }, function (er, pass2) { + console.error({user: user, + pass: pass, + verify: pass2, + four:four, + passMatch: (pass === pass2)}) + console.error("If the program doesn't end right now,\n" + +"then you may be experiencing this bug:\n" + +"https://github.com/joyent/node/issues/2257") + }) + }) + }) +}) diff --git a/node_modules/read/lib/read.js b/node_modules/read/lib/read.js index ba2ef0ae7..eb00fd5c6 100644 --- a/node_modules/read/lib/read.js +++ b/node_modules/read/lib/read.js @@ -6,13 +6,19 @@ var buffer = "" , StringDecoder = require("string_decoder").StringDecoder function raw (mode) { + if (process.stdin.setRawMode) { + if (process.stdin.isTTY) { + process.stdin.setRawMode(mode) + } + return + } + // old style try { - process.stdin.setRawMode(mode) - } catch (e) { tty.setRawMode(mode) - } + } catch (e) {} } + function read (opts, cb) { if (!cb) cb = opts, opts = {} @@ -21,13 +27,13 @@ function read (opts, cb) { , silent = opts.silent , timeout = opts.timeout , num = opts.num || null - , delim = opts.delim || "\n" if (p && def) p += "("+(silent ? "<default hidden>" : def)+") " // switching into raw mode is a little bit painful. // avoid if possible. - var r = silent || num || delim !== "\n" ? rawRead : normalRead + var r = silent || num ? rawRead : normalRead + if (r === rawRead && !process.stdin.isTTY) r = normalRead if (timeout) { cb = (function (cb) { @@ -55,16 +61,16 @@ function read (opts, cb) { if (p && !process.stdout.write(p)) { process.stdout.on("drain", function D () { process.stdout.removeListener("drain", D) - r(def, timeout, delim, silent, num, cb) + r(def, timeout, silent, num, cb) }) } else { process.nextTick(function () { - r(def, timeout, delim, silent, num, cb) + r(def, timeout, silent, num, cb) }) } } -function normalRead (def, timeout, delim, silent, num, cb) { +function normalRead (def, timeout, silent, num, cb) { var stdin = process.openStdin() , val = "" , decoder = new StringDecoder("utf8") @@ -77,23 +83,25 @@ function normalRead (def, timeout, delim, silent, num, cb) { buffer = "" // \r has no place here. - // XXX But what if \r is the delim or something dumb like that? - // Meh. If anyone complains about this, deal with it. val = val.replace(/\r/g, "") - // TODO Make delim configurable - if (val.indexOf(delim) !== -1) { + if (val.indexOf("\n") !== -1) { // pluck off any delims at the beginning. - if (val !== delim) { + if (val !== "\n") { var i, l for (i = 0, l = val.length; i < l; i ++) { - if (val.charAt(i) !== delim) break + if (val.charAt(i) !== "\n") break } if (i !== 0) val = val.substr(i) } + // hack. if we get the number of chars, just pretend there was a delim + if (num > 0 && val.length >= num) { + val = val.substr(0, num) + "\n" + val.substr(num) + } + // buffer whatever might have come *after* the delimter - var delimIndex = val.indexOf(delim) + var delimIndex = val.indexOf("\n") if (delimIndex !== -1) { buffer = val.substr(delimIndex) val = val.substr(0, delimIndex) @@ -112,7 +120,7 @@ function normalRead (def, timeout, delim, silent, num, cb) { }) } -function rawRead (def, timeout, delim, silent, num, cb) { +function rawRead (def, timeout, silent, num, cb) { var stdin = process.openStdin() , val = "" , decoder = new StringDecoder @@ -122,14 +130,17 @@ function rawRead (def, timeout, delim, silent, num, cb) { stdin.on("error", cb) stdin.on("data", function D (c) { // \r is my enemy. - c = decoder.write(c).replace(/\r/g, "\n") + var s = decoder.write(c).replace(/\r/g, "\n") + var i = 0 - switch (c) { - case "": // probably just a \r that was ignored. + LOOP: while (c = s.charAt(i++)) switch (c) { + case "\u007f": // backspace + val = val.substr(0, val.length - 1) + if (!silent) process.stdout.write('\b \b') break case "\u0004": // EOF - case delim: + case "\n": raw(false) stdin.removeListener("data", D) stdin.removeListener("error", cb) @@ -144,16 +155,16 @@ function rawRead (def, timeout, delim, silent, num, cb) { stdin.removeListener("error", cb) stdin.pause() return cb(new Error("cancelled")) - break default: // just a normal char val += buffer + c buffer = "" if (!silent) process.stdout.write(c) - // explicitly process a delim if we have enough chars. - if (num && val.length >= num) D(delim) - break + // explicitly process a delim if we have enough chars + // and stop the processing. + if (num && val.length >= num) D("\n") + break LOOP } }) } diff --git a/node_modules/read/package.json b/node_modules/read/package.json index f206a719b..8057e4493 100644 --- a/node_modules/read/package.json +++ b/node_modules/read/package.json @@ -1,9 +1,11 @@ { "name": "read", - "version": "0.0.2", + "version": "0.1.0", "main": "lib/read.js", "dependencies": {}, - "devDependencies": {}, + "devDependencies": { + "tap": "*" + }, "engines": { "node": ">=0.6" }, @@ -18,11 +20,10 @@ "url": "git://github.com/isaacs/read.git" }, "license": "BSD", - "_id": "read@0.0.2", - "optionalDependencies": {}, - "_engineSupported": true, - "_npmVersion": "1.1.15", - "_nodeVersion": "v0.7.7", - "_defaultsLoaded": true, + "scripts": { + "test": "tap test/*.js" + }, + "readme": "For reading user input from stdin.\n\n## USAGE\n\n```javascript\nvar read = require(\"read\")\nread(options, callback)\n```\n\nThe callback gets called with either the user input, or the default\nspecified, or an error, in the traditional `callback(error, result)`\nnode style.\n\n## OPTIONS\n\nEvery option is optional.\n\n* `prompt` What to write to stdout before reading input.\n* `silent` Don't echo the output as the user types it.\n* `num` Max number of chars to read from terminal.\n* `timeout` Number of ms to wait for user input before giving up.\n* `default` The default value if the user enters nothing.\n\nIf silent is true, or num is set, and the input is a TTY,\nthen read will set raw mode, and read character by character.\n\nAt this time, backspace and arrow keys are not supported very well.\nIt's probably not too hard to add support for this, perhaps using node's\nbuilt-in readline module.\n\n## CONTRIBUTING\n\nPatches welcome.\n\n## BUGS\n\nIn node 0.6.0 through 0.6.5, you must explicitly call\n`process.stdin.destroy()` or `process.exit()` when you know that your\nprogram is done reading, or else it will keep the event loop running\nforever.\n\nSee: <https://github.com/joyent/node/issues/2257>\n", + "_id": "read@0.1.0", "_from": "read@0" } diff --git a/node_modules/read/test/basic.js b/node_modules/read/test/basic.js new file mode 100644 index 000000000..7f195362a --- /dev/null +++ b/node_modules/read/test/basic.js @@ -0,0 +1,54 @@ +var tap = require('tap') +var read = require('../lib/read.js') + +if (process.argv[2] === 'child') { + return child() +} + +var spawn = require('child_process').spawn + +tap.test('basic', function (t) { + var child = spawn(process.execPath, [__filename, 'child']) + var output = '' + child.stdout.on('data', function (c) { + console.error('data %s', c) + output += c + if (output.match(/Username: \(test-user\) $/)) { + child.stdin.write('a user\n') + } else if (output.match(/Password: \(<default hidden>\) $/)) { + child.stdin.write('a password\n') + } else if (output.match(/characters: $/)) { + child.stdin.write('asdf\n') + } else if (output.match(/Password again: \(<default hidden>\) $/)) { + child.stdin.write('a password\n') + } + }) + + var result = '' + child.stderr.on('data', function (c) { + result += c + }) + + child.on('close', function () { + result = JSON.parse(result) + t.same(result, {"user":"a user","pass":"a password","verify":"a password","four":"asdf","passMatch":true}) + t.equal(output, 'Username: (test-user) Password: (<default hidden>) Enter 4 characters: Password again: (<default hidden>) ') + t.end() + }) +}) + +function child () { + read({prompt: "Username: ", default: "test-user" }, function (er, user) { + read({prompt: "Password: ", default: "test-pass", silent: true }, function (er, pass) { + read({prompt: "Enter 4 characters: ", num: 4 }, function (er, four) { + read({prompt: "Password again: ", default: "test-pass", silent: true }, function (er, pass2) { + console.error(JSON.stringify({user: user, + pass: pass, + verify: pass2, + four:four, + passMatch: (pass === pass2)})) + }) + }) + }) + }) +} |