Add options.noEchoBack.

This commit is contained in:
anseki 2014-07-12 07:37:25 +09:00
parent 526e11c7e2
commit 055e4b3060
5 changed files with 77 additions and 46 deletions

View file

@ -30,18 +30,20 @@ Sets the prompt, for example when you run `node` on the command line, you see `>
### prompt
```js
line = readlineSync.prompt()
line = readlineSync.prompt([options])
```
Readies readline for input from the user, putting the current `setPrompt` options on a new line, giving the user a new spot to write.
Readies readline for input from the user, putting the current `setPrompt` options on a new line, giving the user a new spot to write.
If `{noEchoBack: true}` is specified to `options`, echo back is avoided. It is used to hide the password which is typed by user on screen. *See [Note](#note) for security.*
### question
```js
line = readlineSync.question(query)
line = readlineSync.question(query[, options])
```
Displays the `query` to the user, and then returns the user's response after it has been typed.
Displays the `query` to the user, and then returns the user's response after it has been typed.
If `{noEchoBack: true}` is specified to `options`, echo back is avoided. It is used to hide the password which is typed by user on screen. *See [Note](#note) for security.*
### setEncoding
@ -74,7 +76,7 @@ readlineSync.setPrint(function(display, encoding) {
console.log('Your account required.'.grey);
user = readlineSync.question('USER NAME'.white.inverse + ': ');
pw = readlineSync.question('PASSWORD'.white.inverse + ': ', true);
pw = readlineSync.question('PASSWORD'.white.inverse + ': ', {noEchoBack: true});
// Authorization ...
console.log(('Welcome, ' + user + '!').green.bold);
@ -82,8 +84,8 @@ readlineSync.setPrompt('> '.bold.red);
cmd = readlineSync.prompt();
```
## Note
The your Node and OS may not support interactively reading from stdin. The stdin interfaces are different by platforms.
## <a name ="note">Note</a>
+ The your Node and OS may not support interactively reading from stdin. The stdin interfaces are different by platforms.
If in those platforms, an error is thrown.
```js
@ -95,8 +97,11 @@ try {
}
```
+ If `options.noEchoBack` is used, the text that input by user is saved to temporary file (e.g. `/tmp/readline-sync.stdout`). This file is removed immediately after reading is done, but you have to be careful about it because this text is *plain*. Removing the file might fail, or the file might be peeped before it is removed.
## Release History
* 2014-07-12 v0.3.0 Add setPrint().
* 2014-07-12 v0.4.0 Add `options.noEchoBack`.
* 2014-07-12 v0.3.0 Add `setPrint()`.
* 2014-06-27 v0.2.3 Add alternative reading via shell on the environment which don't support interactively reading.
* 2013-12-18 v0.2.2 Error handle for the environment which don't support interactively reading from stdin.
* 2013-08-30 v0.2.0 Rewrite exporting methods.

View file

@ -1,6 +1,11 @@
@echo off
setlocal
set /p LINE=<CON >CON
if "%1"=="noechoback" (
set /p LINE=<CON >NUL
echo; >CON
) else (
set /p LINE=<CON >CON
)
set /p DUM="%LINE%"<NUL
endlocal
exit /b 0

View file

@ -1,3 +1,10 @@
read LINE </dev/tty
if [ "$1" = "noechoback" ]; then
stty -F /dev/tty -echo echonl
read LINE </dev/tty
stty -F /dev/tty echo -echonl
# printf '\n' >/dev/tty
else
read LINE </dev/tty
fi
printf '%s' "$LINE"
exit 0

View file

@ -17,7 +17,7 @@ var promptText = '> ',
buffer = new Buffer(BUF_SIZE),
useShell = true, print, tempdir;
function _readlineSync(display) {
function _readlineSync(display, options) {
var input = '', rsize, err;
if (display) {
@ -25,56 +25,70 @@ function _readlineSync(display) {
stdout.write(display, encoding);
}
stdin.resume();
while (true) {
rsize = 0;
if (options && options.noEchoBack) { // Try reading via shell
try {
rsize = fs.readSync(stdin.fd, buffer, 0, BUF_SIZE);
} catch (e) {
if (e.code === 'EOF') { break; } // pipe
if (useShell) {
// Try reading via shell
input = _readlineShell();
if (typeof input === 'string') { break; }
}
// Give up...
if (e.code === 'EAGAIN') { // EAGAIN, resource temporarily unavailable
// util can't inherit Error.
err = new Error('The platform doesn\'t support interactive reading from stdin');
err.errno = e.errno;
err.code = e.code;
}
input = _readlineShell(true);
if (typeof input !== 'string') {
if (display) { stdout.write('\n', encoding); } // Return from prompt line.
throw err || e;
throw new Error('Can\'t read via shell');
}
if (rsize === 0) { break; }
input += buffer.toString(encoding, 0, rsize);
if (/[\r\n]$/.test(input)) { break; }
} else {
stdin.resume();
while (true) {
rsize = 0;
try {
rsize = fs.readSync(stdin.fd, buffer, 0, BUF_SIZE);
} catch (e) {
if (e.code === 'EOF') { break; } // pipe
if (useShell) {
// Try reading via shell
input = _readlineShell();
if (typeof input === 'string') { break; }
}
// Give up...
if (e.code === 'EAGAIN') { // EAGAIN, resource temporarily unavailable
// util can't inherit Error.
err = new Error('The platform doesn\'t support interactive reading from stdin');
err.errno = e.errno;
err.code = e.code;
}
if (display) { stdout.write('\n', encoding); } // Return from prompt line.
throw err || e;
}
if (rsize === 0) { break; }
input += buffer.toString(encoding, 0, rsize);
if (/[\r\n]$/.test(input)) { break; }
}
stdin.pause();
}
stdin.pause();
return input.trim();
}
function _readlineShell() {
function _readlineShell(noEchoBack) {
// piping via files instead of execSync (node v0.12+)
var shellPath, args, shellStdout,
pathStdout = getTempfile('readline-sync.stdout'),
pathStatus = getTempfile('readline-sync.status'),
pathDone = getTempfile('readline-sync.done');
pathDone = getTempfile('readline-sync.done'),
optEchoBack = noEchoBack ? ' noechoback' : '';
if (process.platform === 'win32') {
// The quote (") is escaped by node before parsed by shell. Then use ENV{Q}.
shellPath = 'cmd.exe';
args = ['/V:ON', '/S', '/C', '%Q%' + __dirname + '\\read.bat%Q% >%Q%' + pathStdout +
args = ['/V:ON', '/S', '/C',
'%Q%' + __dirname + '\\read.bat%Q%' + optEchoBack + ' >%Q%' + pathStdout +
'%Q% & (echo !ERRORLEVEL!)>%Q%' + pathStatus + '%Q% & (echo 1)>%Q%' + pathDone + '%Q%'];
} else {
shellPath = '/bin/sh';
args = ['-c', '(' + shellPath + ' "' + __dirname + '/read.sh") >"' + pathStdout +
args = ['-c', '(' + shellPath + ' "' + __dirname + '/read.sh"' + optEchoBack + ') >"' + pathStdout +
'"; echo $? >"' + pathStatus + '"; echo 1 >"' + pathDone + '"'];
}
@ -133,10 +147,10 @@ exports.setEncoding = function(newEncoding) {
}
};
exports.prompt = function() {
return _readlineSync(promptText);
exports.prompt = function(options) {
return _readlineSync(promptText, options);
};
exports.question = function(query) {
return _readlineSync(typeof query === 'string' ? query : '');
exports.question = function(query, options) {
return _readlineSync(typeof query === 'string' ? query : '', options);
};

View file

@ -1,7 +1,7 @@
{
"name": "readline-sync",
"description": "Synchronous Readline",
"version": "0.3.0",
"version": "0.4.0",
"homepage": "https://github.com/anseki/readline-sync",
"author": {
"name": "anseki"