Add getRawInput method, fix #36

This commit is contained in:
anseki 2016-10-28 15:16:59 +09:00
parent e39454cd2b
commit 90f173ad92
3 changed files with 40 additions and 18 deletions

View file

@ -479,7 +479,7 @@ _For `question*` and `prompt*` methods only_
*Type:* number *Type:* number
*Default:* `1024` *Default:* `1024`
When readlineSync reads from a console directly (without external program), use a size `bufferSize` buffer. When readlineSync reads from a console directly (without [external program](#note-reading_by_external_program)), use a size `bufferSize` buffer.
Even if the input by user exceeds it, it's usually no problem, because the buffer is used repeatedly. But some platforms's (e.g. Windows) console might not accept input that exceeds it. And set an enough size. Even if the input by user exceeds it, it's usually no problem, because the buffer is used repeatedly. But some platforms's (e.g. Windows) console might not accept input that exceeds it. And set an enough size.
Note that this might be limited by [version of Node.js](https://nodejs.org/api/buffer.html#buffer_class_method_buffer_alloc_size_fill_encoding) and environment running your script (Big buffer size is usually not required). (See also: [issue](https://github.com/nodejs/node/issues/4660), [PR](https://github.com/nodejs/node/pull/4682)) Note that this might be limited by [version of Node.js](https://nodejs.org/api/buffer.html#buffer_class_method_buffer_alloc_size_fill_encoding) and environment running your script (Big buffer size is usually not required). (See also: [issue](https://github.com/nodejs/node/issues/4660), [PR](https://github.com/nodejs/node/pull/4682))
@ -1728,6 +1728,19 @@ password = readlineSync.questionNewPassword('PASSWORD: ', {charlist: '$<a-z>'});
See also [`limit` option for `keyIn*` method](#basic_options-limit-for_keyin_method). See also [`limit` option for `keyIn*` method](#basic_options-limit-for_keyin_method).
## Special method `getRawInput`
```js
rawInput = readlineSync.getRawInput()
```
Return a raw input data of last method.
When the input was terminated with no data, a `NULL` is inserted to the data.
This might contain control-codes (e.g. `LF`, `CR`, `EOF`, etc.), therefore, it might be used to get `^D` that was input. But you should understand each environments for that. Or, **you should not use this** if your script is used in multiple environments.
For example, when the user input `EOF` (`^D` in Unix like system, `^Z` in Windows), `x1A` (`EOF`) is returned in Windows, and `x00` (`NULL`) is returned in Unix like system. And `x04` (`EOT`) is returned in Unix like system with raw-mode. And also, when [external program](#note-reading_by_external_program) is used, nothing is returned. See also [Control characters](#note-control_characters).
You may examine each environment and you must test your script very much, if you want to handle the raw input data.
## <a name="with_task_runner"></a>With Task Runner ## <a name="with_task_runner"></a>With Task Runner
The easy way to control a flow of the task runner by the input from the user: The easy way to control a flow of the task runner by the input from the user:
@ -1790,7 +1803,7 @@ try {
} }
``` ```
### <a name="note-platforms"></a>Control characters ### <a name="note-control_characters"></a>Control characters
TTY interfaces are different by the platforms. In some environments, ANSI escape sequences might be ignored. For example, in non-POSIX TTY such as Windows CMD does not support it (that of Windows 8 especially has problems). Since readlineSync does not use Node.js library that emulates POSIX TTY (but that is still incomplete), those characters may be not parsed. Then, using ANSI escape sequences is not recommended if you will support more environments. TTY interfaces are different by the platforms. In some environments, ANSI escape sequences might be ignored. For example, in non-POSIX TTY such as Windows CMD does not support it (that of Windows 8 especially has problems). Since readlineSync does not use Node.js library that emulates POSIX TTY (but that is still incomplete), those characters may be not parsed. Then, using ANSI escape sequences is not recommended if you will support more environments.
Also, control characters user input might be not accepted or parsed. That behavior differs depending on the environment. And current Node.js does not support controlling a readline system library. Also, control characters user input might be not accepted or parsed. That behavior differs depending on the environment. And current Node.js does not support controlling a readline system library.

View file

@ -44,7 +44,7 @@ var
fdR = 'none', fdW, ttyR, isRawMode = false, fdR = 'none', fdW, ttyR, isRawMode = false,
extHostPath, extHostArgs, tempdir, salt = 0, extHostPath, extHostArgs, tempdir, salt = 0,
lastInput = '', inputHistory = [], lastInput = '', inputHistory = [], rawInput,
_DBG_useExt = false, _DBG_checkOptions = false, _DBG_checkMethod = false; _DBG_useExt = false, _DBG_checkOptions = false, _DBG_checkMethod = false;
function getHostArgs(options) { function getHostArgs(options) {
@ -337,6 +337,7 @@ function _readlineSync(options) {
var atEol, limit, var atEol, limit,
isCooked = !options.hideEchoBack && !options.keyIn, isCooked = !options.hideEchoBack && !options.keyIn,
buffer, reqSize, readSize, chunk, line; buffer, reqSize, readSize, chunk, line;
rawInput = '';
// Node.js v0.10- returns an error if same mode is set. // Node.js v0.10- returns an error if same mode is set.
function setRawMode(mode) { function setRawMode(mode) {
@ -387,7 +388,13 @@ function _readlineSync(options) {
return; return;
} }
} }
chunk = readSize > 0 ? buffer.toString(options.encoding, 0, readSize) : '\n'; if (readSize > 0) {
chunk = buffer.toString(options.encoding, 0, readSize);
rawInput += chunk;
} else {
chunk = '\n';
rawInput += String.fromCharCode(0);
}
if (chunk && typeof (line = (chunk.match(/^(.*?)[\r\n]/) || [])[1]) === 'string') { if (chunk && typeof (line = (chunk.match(/^(.*?)[\r\n]/) || [])[1]) === 'string') {
chunk = line; chunk = line;
@ -432,7 +439,7 @@ function _readlineSync(options) {
function flattenArray(array, validator) { function flattenArray(array, validator) {
var flatArray = []; var flatArray = [];
function _flattenArray(array) { function _flattenArray(array) {
if (array == null) { // eslint-disable-line eqeqeq if (array == null) {
return; return;
} else if (Array.isArray(array)) { } else if (Array.isArray(array)) {
array.forEach(_flattenArray); array.forEach(_flattenArray);
@ -465,7 +472,7 @@ function margeOptions() {
} }
return optionsList.reduce(function(options, optionsPart) { return optionsList.reduce(function(options, optionsPart) {
if (optionsPart == null) { return options; } // eslint-disable-line eqeqeq if (optionsPart == null) { return options; }
// ======== DEPRECATED ======== // ======== DEPRECATED ========
if (optionsPart.hasOwnProperty('noEchoBack') && if (optionsPart.hasOwnProperty('noEchoBack') &&
@ -492,7 +499,7 @@ function margeOptions() {
case 'limitMessage': // * case 'limitMessage': // *
case 'defaultInput': // * case 'defaultInput': // *
case 'encoding': // * * case 'encoding': // * *
value = value != null ? value + '' : ''; // eslint-disable-line eqeqeq value = value != null ? value + '' : '';
if (value && optionName !== 'limitMessage') { value = value.replace(/[\r\n]/g, ''); } if (value && optionName !== 'limitMessage') { value = value.replace(/[\r\n]/g, ''); }
options[optionName] = value; options[optionName] = value;
break; break;
@ -533,7 +540,7 @@ function margeOptions() {
// ================ other // ================ other
case 'prompt': // * case 'prompt': // *
case 'display': // * case 'display': // *
options[optionName] = value != null ? value : ''; // eslint-disable-line eqeqeq options[optionName] = value != null ? value : '';
break; break;
// no default // no default
} }
@ -877,7 +884,7 @@ exports.keyIn = function(query, options) {
// ------------------------------------ // ------------------------------------
exports.questionEMail = function(query, options) { exports.questionEMail = function(query, options) {
if (query == null) { query = 'Input e-mail address: '; } // eslint-disable-line eqeqeq if (query == null) { query = 'Input e-mail address: '; }
/* eslint-disable key-spacing */ /* eslint-disable key-spacing */
return exports.question(query, margeOptions({ return exports.question(query, margeOptions({
// -------- default // -------- default
@ -932,13 +939,13 @@ exports.questionNewPassword = function(query, options) {
resCharlist = array2charlist([charlist], readOptions.caseSensitive, true); resCharlist = array2charlist([charlist], readOptions.caseSensitive, true);
resCharlist.text = joinChunks(resCharlist.values, resCharlist.suppressed); resCharlist.text = joinChunks(resCharlist.values, resCharlist.suppressed);
confirmMessage = options.confirmMessage != null ? options.confirmMessage : // eslint-disable-line eqeqeq confirmMessage = options.confirmMessage != null ? options.confirmMessage :
'Reinput a same one to confirm it: '; 'Reinput a same one to confirm it: ';
unmatchMessage = options.unmatchMessage != null ? options.unmatchMessage : // eslint-disable-line eqeqeq unmatchMessage = options.unmatchMessage != null ? options.unmatchMessage :
'It differs from first one.' + 'It differs from first one.' +
' Hit only the Enter key if you want to retry from first one.'; ' Hit only the Enter key if you want to retry from first one.';
if (query == null) { query = 'Input new password: '; } // eslint-disable-line eqeqeq if (query == null) { query = 'Input new password: '; }
limitMessage = readOptions.limitMessage; limitMessage = readOptions.limitMessage;
while (!res2) { while (!res2) {
@ -1067,7 +1074,7 @@ exports.questionPath = function(query, options) {
/* eslint-enable key-spacing */ /* eslint-enable key-spacing */
options = options || {}; options = options || {};
if (query == null) { query = 'Input path (you can "cd" and "pwd"): '; } // eslint-disable-line eqeqeq if (query == null) { query = 'Input path (you can "cd" and "pwd"): '; }
exports.question(query, readOptions); exports.question(query, readOptions);
return validPath; return validPath;
@ -1192,7 +1199,7 @@ exports.promptSimShell = function(options) {
function _keyInYN(query, options, limit) { function _keyInYN(query, options, limit) {
var res; var res;
if (query == null) { query = 'Are you sure? '; } // eslint-disable-line eqeqeq if (query == null) { query = 'Are you sure? '; }
if ((!options || options.guide !== false) && (query += '')) { if ((!options || options.guide !== false) && (query += '')) {
query = query.replace(/\s*:?\s*$/, '') + ' [y/n]: '; query = query.replace(/\s*:?\s*$/, '') + ' [y/n]: ';
} }
@ -1214,7 +1221,7 @@ exports.keyInYN = function(query, options) { return _keyInYN(query, options); };
exports.keyInYNStrict = function(query, options) { return _keyInYN(query, options, 'yn'); }; exports.keyInYNStrict = function(query, options) { return _keyInYN(query, options, 'yn'); };
exports.keyInPause = function(query, options) { exports.keyInPause = function(query, options) {
if (query == null) { query = 'Continue...'; } // eslint-disable-line eqeqeq if (query == null) { query = 'Continue...'; }
if ((!options || options.guide !== false) && (query += '')) { if ((!options || options.guide !== false) && (query += '')) {
query = query.replace(/\s+$/, '') + ' (Hit any key)'; query = query.replace(/\s+$/, '') + ' (Hit any key)';
} }
@ -1267,13 +1274,13 @@ exports.keyInSelect = function(items, query, options) {
keylist += '0'; keylist += '0';
key2i['0'] = -1; key2i['0'] = -1;
display += '[0] ' + display += '[0] ' +
(options && options.cancel != null && typeof options.cancel !== 'boolean' ? // eslint-disable-line eqeqeq (options && options.cancel != null && typeof options.cancel !== 'boolean' ?
(options.cancel + '').trim() : 'CANCEL') + '\n'; (options.cancel + '').trim() : 'CANCEL') + '\n';
} }
readOptions.limit = keylist; readOptions.limit = keylist;
display += '\n'; display += '\n';
if (query == null) { query = 'Choose one from list: '; } // eslint-disable-line eqeqeq if (query == null) { query = 'Choose one from list: '; }
if ((query += '')) { if ((query += '')) {
if (!options || options.guide !== false) { if (!options || options.guide !== false) {
query = query.replace(/\s*:?\s*$/, '') + ' [$<limit>]: '; query = query.replace(/\s*:?\s*$/, '') + ' [$<limit>]: ';
@ -1284,6 +1291,8 @@ exports.keyInSelect = function(items, query, options) {
return key2i[exports.keyIn(display, readOptions).toLowerCase()]; return key2i[exports.keyIn(display, readOptions).toLowerCase()];
}; };
exports.getRawInput = function() { return rawInput; };
// ======== DEPRECATED ======== // ======== DEPRECATED ========
function _setOption(optionName, args) { function _setOption(optionName, args) {
var options; var options;

View file

@ -1,6 +1,6 @@
{ {
"name": "readline-sync", "name": "readline-sync",
"version": "1.4.4", "version": "1.4.5",
"title": "readlineSync", "title": "readlineSync",
"description": "Synchronous Readline for interactively running to have a conversation with the user via a console(TTY).", "description": "Synchronous Readline for interactively running to have a conversation with the user via a console(TTY).",
"keywords": [ "keywords": [