Fix: keyIn gets NL

This commit is contained in:
anseki 2015-04-01 16:34:31 +09:00
parent 4037ba9845
commit 6dffd81b65
6 changed files with 50 additions and 33 deletions

View file

@ -252,12 +252,3 @@ Why did I choose it? :
+ The good modules (native addon) for synchronous execution exist. But node-gyp can't compile those in some platforms or Node versions. + The good modules (native addon) for synchronous execution exist. But node-gyp can't compile those in some platforms or Node versions.
+ I think that the security is important more than the speed. Some modules have problem about security. (Those don't protect data.) I think that the speed is not needed usually, because readlineSync is used while user types keys. + I think that the security is important more than the speed. Some modules have problem about security. (Those don't protect data.) I think that the speed is not needed usually, because readlineSync is used while user types keys.
## Release History
* 2015-02-22 v0.6.0 Add `setBufferSize()`.
* 2015-02-12 v0.5.5 Support the Synchronous Process Execution of Node v0.12(v0.11).
* 2015-01-27 v0.5.0 Add `options.noTrim`.
* 2014-07-12 v0.4.0 Add `options.noEchoBack`.
* 2014-07-12 v0.3.0 Add `setPrint()`.
* 2013-08-30 v0.2.0 Rewrite exporting methods.
* 2013-08-29 v0.1.0 Initial release.

View file

@ -1,3 +1,11 @@
/*
* readlineSync
* https://github.com/anseki/readline-sync
*
* Copyright (c) 2015 anseki
* Licensed under the MIT license.
*/
var cipher = require('crypto').createCipher( var cipher = require('crypto').createCipher(
process.argv[2] /*algorithm*/, process.argv[3] /*password*/), process.argv[2] /*algorithm*/, process.argv[3] /*password*/),
stdin = process.stdin, stdin = process.stdin,

View file

@ -1,4 +1,12 @@
/*jshint wsh:true */ /* jshint wsh:true */
/*
* readlineSync
* https://github.com/anseki/readline-sync
*
* Copyright (c) 2015 anseki
* Licensed under the MIT license.
*/
var var
FSO_ForReading = 1, FSO_ForWriting = 2, FSO_ForReading = 1, FSO_ForWriting = 2,

View file

@ -1,3 +1,8 @@
# readlineSync
# https://github.com/anseki/readline-sync
#
# Copyright (c) 2015 anseki
# Licensed under the MIT license.
Param( Param(
[string] $display, [string] $display,
@ -38,22 +43,23 @@ if ($options.encoded) {
[bool] $isCooked = (-not $options.noEchoBack) -and (-not $options.keyIn) [bool] $isCooked = (-not $options.noEchoBack) -and (-not $options.keyIn)
function writeTTY ($text) { function writeTTY ($text) {
execWithTTY ('Write-Host ''' + ($text -replace '''', '''''') + ''' -NoNewline') | Out-Null execWithTTY ('Write-Host ''' + ($text -replace '''', '''''') + ''' -NoNewline')
$script:isInputLine = $True $script:isInputLine = $True
} }
# Instant method that opens TTY without CreateFile via P/Invoke in .NET Framework # Instant method that opens TTY without CreateFile via P/Invoke in .NET Framework
# **NOTE** Don't include special characters of DOS in $command when $getRes is True. # **NOTE** Don't include special characters of DOS in $command when $getRes is True.
# [string] $cmdPath = $Env:ComSpec
# [string] $psPath = 'powershell.exe'
function execWithTTY ($command, $getRes = $False) { function execWithTTY ($command, $getRes = $False) {
if ($getRes) { if ($getRes) {
$res = (cmd.exe /C "<CON powershell.exe -Command $command") $res = (cmd.exe /C "<CON powershell.exe -Command $command")
if ($LastExitCode -ne 0) { exit 1 } if ($LastExitCode -ne 0) { exit 1 }
return $res
} else { } else {
$command | cmd.exe /C ">CON powershell.exe -Command -" $command | cmd.exe /C ">CON powershell.exe -Command -"
if ($LastExitCode -ne 0) { exit 1 } if ($LastExitCode -ne 0) { exit 1 }
$res = ''
} }
return $res
} }
if ($options.display -ne '') { if ($options.display -ne '') {
@ -76,11 +82,11 @@ while ($True) {
# ReadKey() may returns [System.Array], then don't cast data. # ReadKey() may returns [System.Array], then don't cast data.
if ($chunk -isnot [string]) { $chunk = '' } if ($chunk -isnot [string]) { $chunk = '' }
$chunk = $chunk -replace '[\r\n]', '' $chunk = $chunk -replace '[\r\n]', ''
if ($chunk -eq '') { $isEol = $True } # NL or empty-text was input if ($chunk -eq '') { $atEol = $True } # NL or empty-text was input
} else { } else {
$chunk = execWithTTY 'Read-Host' $True $chunk = execWithTTY 'Read-Host' $True
$chunk = $chunk -replace '[\r\n]', '' $chunk = $chunk -replace '[\r\n]', ''
$isEol = $True $atEol = $True
} }
# other ctrl-chars # other ctrl-chars
@ -95,10 +101,10 @@ while ($True) {
} }
$inputTTY += $chunk $inputTTY += $chunk
if ($isEol -or ($options.keyIn -and ($inputTTY.Length -ge $reqSize))) { break } if ($atEol -or ($options.keyIn -and ($inputTTY.Length -ge $reqSize))) { break }
} }
if ((-not $isCooked) -and (-not ($options.keyIn -and (-not $isInputLine)))) if ((-not $isCooked) -and (-not ($options.keyIn -and (-not $isInputLine))))
{ execWithTTY 'Write-Host ''''' | Out-Null } # new line { execWithTTY 'Write-Host ''''' } # new line
return '''' + $inputTTY + '''' return '''' + $inputTTY + ''''

View file

@ -1,3 +1,8 @@
# readlineSync
# https://github.com/anseki/readline-sync
#
# Copyright (c) 2015 anseki
# Licensed under the MIT license.
# getopt(s) # getopt(s)
while [ $# -ge 1 ]; do while [ $# -ge 1 ]; do
@ -62,11 +67,11 @@ do
if [ -z "$is_cooked" ]; then if [ -z "$is_cooked" ]; then
chunk="$(dd if=/dev/tty bs=1 count=1 2>/dev/null)" chunk="$(dd if=/dev/tty bs=1 count=1 2>/dev/null)"
chunk="$(printf '%s' "$chunk" | tr -d '\r\n')" chunk="$(printf '%s' "$chunk" | tr -d '\r\n')"
[ -z "$chunk" ] && is_eol='true' # NL or empty-text was input [ -z "$chunk" ] && at_eol='true' # NL or empty-text was input
else else
IFS= read -r chunk </dev/tty || exit $? IFS= read -r chunk </dev/tty || exit $?
chunk="$(printf '%s' "$chunk" | tr -d '\r\n')" chunk="$(printf '%s' "$chunk" | tr -d '\r\n')"
is_eol='true' at_eol='true'
fi fi
# other ctrl-chars # other ctrl-chars
@ -83,7 +88,7 @@ do
fi fi
input="$input$chunk" input="$input$chunk"
if [ -n "$is_eol" ] || \ if [ -n "$at_eol" ] || \
( [ -n "$options_keyIn" ] && [ ${#input} -ge $req_size ] ); then break; fi ( [ -n "$options_keyIn" ] && [ ${#input} -ge $req_size ] ); then break; fi
done done

View file

@ -113,8 +113,9 @@ function readlineSync(options) {
})(); })();
(function() { // try read (function() { // try read
var buffer, reqSize, readSize, chunk, isEol, line, exclude, var atEol, exclude,
isCooked = !options.noEchoBack && !options.keyIn; isCooked = !options.noEchoBack && !options.keyIn,
buffer, reqSize, readSize, chunk, line;
// Node v0.10- returns an error if same mode is set. // Node v0.10- returns an error if same mode is set.
function setRawMode(mode) { function setRawMode(mode) {
@ -140,7 +141,7 @@ function readlineSync(options) {
} }
buffer = new Buffer((reqSize = options.keyIn ? 1 : bufSize)); buffer = new Buffer((reqSize = options.keyIn ? 1 : bufSize));
if (options.exclude) { if (options.keyIn && options.exclude) {
exclude = new RegExp(options.exclude, 'g' + (options.cs ? '' : 'i')); exclude = new RegExp(options.exclude, 'g' + (options.cs ? '' : 'i'));
} }
@ -157,16 +158,13 @@ function readlineSync(options) {
} }
chunk = readSize > 0 ? buffer.toString(encoding, 0, readSize) : '\n'; chunk = readSize > 0 ? buffer.toString(encoding, 0, readSize) : '\n';
if (!isCooked) { if (typeof(line = (chunk.match(/^(.*?)[\r\n]/) || [])[1]) === 'string') {
chunk = chunk.replace(/[\r\n]/g, '');
if (!chunk) { isEol = true; } // NL or empty-text was input
} else if (typeof(line = (chunk.match(/^(.*?)[\r\n]/) || [])[1]) === 'string') {
chunk = line; chunk = line;
isEol = true; atEol = true;
} }
chunk = chunk.replace(/[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]/g, ''); // other ctrl-chars chunk = chunk.replace(/[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]/g, ''); // other ctrl-chars
if (chunk && options.keyIn && exclude) { chunk = chunk.replace(exclude, ''); } if (chunk && exclude) { chunk = chunk.replace(exclude, ''); }
if (chunk && !isCooked) { if (chunk && !isCooked) {
if (!options.noEchoBack) { if (!options.noEchoBack) {
@ -177,7 +175,8 @@ function readlineSync(options) {
} }
input += chunk; input += chunk;
if (isEol || options.keyIn && input.length >= reqSize) { break; } if (!options.keyIn && atEol ||
options.keyIn && input.length >= reqSize) { break; }
} }
if (!isCooked && !silent) { fs.writeSync(fdW, '\n'); } if (!isCooked && !silent) { fs.writeSync(fdW, '\n'); }
@ -454,7 +453,7 @@ exports.question = function(query, options) {
exports.keyIn = function(query, options) { exports.keyIn = function(query, options) {
var limit = options ? flattenArray(options.limit, function(value) { var limit = options ? flattenArray(options.limit, function(value) {
return typeof value === 'string' || typeof value === 'number'; }) : [], return typeof value === 'string' || typeof value === 'number'; }).join('') : '',
readOptions = { readOptions = {
/* jshint eqnull:true */ /* jshint eqnull:true */
display: query != null ? query + '' : '', display: query != null ? query + '' : '',
@ -462,8 +461,8 @@ exports.keyIn = function(query, options) {
keyIn: true, keyIn: true,
noEchoBack: !!(options && options.noEchoBack), noEchoBack: !!(options && options.noEchoBack),
mask: mask, mask: mask,
exclude: limit.length ? exclude: limit ? '[^' +
'[^' + limit.join('').replace(/\W/g, '\\$&') + ']' : '', limit.replace(/\n/g, '').replace(/\W/g, '\\$&') + ']' : '',
cs: !!(options && options.caseSensitive), cs: !!(options && options.caseSensitive),
noTrim: true noTrim: true
}; };