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
*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.
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).
## 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
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.
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,
extHostPath, extHostArgs, tempdir, salt = 0,
lastInput = '', inputHistory = [],
lastInput = '', inputHistory = [], rawInput,
_DBG_useExt = false, _DBG_checkOptions = false, _DBG_checkMethod = false;
function getHostArgs(options) {
@ -337,6 +337,7 @@ function _readlineSync(options) {
var atEol, limit,
isCooked = !options.hideEchoBack && !options.keyIn,
buffer, reqSize, readSize, chunk, line;
rawInput = '';
// Node.js v0.10- returns an error if same mode is set.
function setRawMode(mode) {
@ -387,7 +388,13 @@ function _readlineSync(options) {
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') {
chunk = line;
@ -432,7 +439,7 @@ function _readlineSync(options) {
function flattenArray(array, validator) {
var flatArray = [];
function _flattenArray(array) {
if (array == null) { // eslint-disable-line eqeqeq
if (array == null) {
return;
} else if (Array.isArray(array)) {
array.forEach(_flattenArray);
@ -465,7 +472,7 @@ function margeOptions() {
}
return optionsList.reduce(function(options, optionsPart) {
if (optionsPart == null) { return options; } // eslint-disable-line eqeqeq
if (optionsPart == null) { return options; }
// ======== DEPRECATED ========
if (optionsPart.hasOwnProperty('noEchoBack') &&
@ -492,7 +499,7 @@ function margeOptions() {
case 'limitMessage': // *
case 'defaultInput': // *
case 'encoding': // * *
value = value != null ? value + '' : ''; // eslint-disable-line eqeqeq
value = value != null ? value + '' : '';
if (value && optionName !== 'limitMessage') { value = value.replace(/[\r\n]/g, ''); }
options[optionName] = value;
break;
@ -533,7 +540,7 @@ function margeOptions() {
// ================ other
case 'prompt': // *
case 'display': // *
options[optionName] = value != null ? value : ''; // eslint-disable-line eqeqeq
options[optionName] = value != null ? value : '';
break;
// no default
}
@ -877,7 +884,7 @@ exports.keyIn = 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 */
return exports.question(query, margeOptions({
// -------- default
@ -932,13 +939,13 @@ exports.questionNewPassword = function(query, options) {
resCharlist = array2charlist([charlist], readOptions.caseSensitive, true);
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: ';
unmatchMessage = options.unmatchMessage != null ? options.unmatchMessage : // eslint-disable-line eqeqeq
unmatchMessage = options.unmatchMessage != null ? options.unmatchMessage :
'It differs 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;
while (!res2) {
@ -1067,7 +1074,7 @@ exports.questionPath = function(query, options) {
/* eslint-enable key-spacing */
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);
return validPath;
@ -1192,7 +1199,7 @@ exports.promptSimShell = function(options) {
function _keyInYN(query, options, limit) {
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 += '')) {
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.keyInPause = function(query, options) {
if (query == null) { query = 'Continue...'; } // eslint-disable-line eqeqeq
if (query == null) { query = 'Continue...'; }
if ((!options || options.guide !== false) && (query += '')) {
query = query.replace(/\s+$/, '') + ' (Hit any key)';
}
@ -1267,13 +1274,13 @@ exports.keyInSelect = function(items, query, options) {
keylist += '0';
key2i['0'] = -1;
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';
}
readOptions.limit = keylist;
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 (!options || options.guide !== false) {
query = query.replace(/\s*:?\s*$/, '') + ' [$<limit>]: ';
@ -1284,6 +1291,8 @@ exports.keyInSelect = function(items, query, options) {
return key2i[exports.keyIn(display, readOptions).toLowerCase()];
};
exports.getRawInput = function() { return rawInput; };
// ======== DEPRECATED ========
function _setOption(optionName, args) {
var options;

View file

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