Don't write an undesired line-break.
This commit is contained in:
parent
b3d633cb1c
commit
e49c13d677
3 changed files with 161 additions and 93 deletions
115
lib/read.cs.js
115
lib/read.cs.js
|
@ -3,34 +3,42 @@
|
||||||
var
|
var
|
||||||
FSO_ForReading = 1, FSO_ForWriting = 2,
|
FSO_ForReading = 1, FSO_ForWriting = 2,
|
||||||
|
|
||||||
fso, tty, shell,
|
fso, tty,
|
||||||
args =// Array.prototype.slice.call(WScript.Arguments),
|
args =// Array.prototype.slice.call(WScript.Arguments),
|
||||||
(function() {
|
(function() {
|
||||||
var args = [], i, iLen;
|
var args = [], i, iLen;
|
||||||
for (i = 0, iLen = WScript.Arguments.length; i < iLen; i++) {
|
for (i = 0, iLen = WScript.Arguments.length; i < iLen; i++)
|
||||||
args.push(WScript.Arguments(i));
|
{ args.push(WScript.Arguments(i)); }
|
||||||
}
|
|
||||||
return args;
|
return args;
|
||||||
})(),
|
})(),
|
||||||
arg, options = {};
|
arg, options = {};
|
||||||
|
|
||||||
while (typeof(arg = args.shift()) === 'string') {
|
while (typeof(arg = args.shift()) === 'string') {
|
||||||
if (arg === '--noechoback') {
|
arg = arg.toLowerCase();
|
||||||
|
if (arg === '--display') {
|
||||||
|
options.display = args.shift();
|
||||||
|
} else if (arg === '--noechoback') {
|
||||||
options.noEchoBack = true;
|
options.noEchoBack = true;
|
||||||
|
} else if (arg === '--mask') {
|
||||||
|
options.mask = args.shift();
|
||||||
} else if (arg === '--keyin') {
|
} else if (arg === '--keyin') {
|
||||||
options.keyIn = true;
|
options.keyIn = true;
|
||||||
} else if (arg === '--display') {
|
|
||||||
options.display = args.shift();
|
|
||||||
} else if (arg === '--encoded') {
|
} else if (arg === '--encoded') {
|
||||||
options.encoded = true;
|
options.encoded = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof options.display === 'string' && options.display !== '') {
|
if (options.encoded) {
|
||||||
writeTTY(options.encoded ? decodeDOS(options.display) : options.display);
|
if (typeof options.display === 'string')
|
||||||
|
{ options.display = decodeDOS(options.display); }
|
||||||
|
if (typeof options.mask === 'string')
|
||||||
|
{ options.mask = decodeDOS(options.mask); }
|
||||||
}
|
}
|
||||||
|
|
||||||
WScript.StdOut.Write("'" + (options.noEchoBack ? readS() : readTTY()) + "'");
|
if (typeof options.display === 'string' && options.display !== '')
|
||||||
|
{ writeTTY(options.display); }
|
||||||
|
|
||||||
|
WScript.StdOut.Write("'" + readTTY() + "'");
|
||||||
|
|
||||||
WScript.Quit();
|
WScript.Quit();
|
||||||
|
|
||||||
|
@ -46,6 +54,27 @@ function writeTTY(text) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function readTTY() {
|
function readTTY() {
|
||||||
|
|
||||||
|
// function psExists() {
|
||||||
|
// var envPs = getShell().Environment('System')('PSModulePath');
|
||||||
|
// return typeof envPs === 'string' && envPs !== '';
|
||||||
|
// }
|
||||||
|
|
||||||
|
if (!options.noEchoBack && !options.keyIn) {
|
||||||
|
return readByCS();
|
||||||
|
// } else if (psExists()) {
|
||||||
|
// return readByPS();
|
||||||
|
} else if (options.noEchoBack && !options.keyIn && options.mask === '*') {
|
||||||
|
return readByPW();
|
||||||
|
} else {
|
||||||
|
WScript.StdErr.WriteLine('Microsoft Windows PowerShell is required.\n' +
|
||||||
|
'https://technet.microsoft.com/ja-jp/library/hh847837.aspx');
|
||||||
|
WScript.Quit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function readByCS() {
|
||||||
|
WScript.StdErr.Write('<<readByCS>>'); //_DBG_
|
||||||
var text;
|
var text;
|
||||||
try {
|
try {
|
||||||
text = getFso().OpenTextFile('CONIN$', FSO_ForReading).ReadLine();
|
text = getFso().OpenTextFile('CONIN$', FSO_ForReading).ReadLine();
|
||||||
|
@ -57,32 +86,8 @@ function readTTY() {
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
|
|
||||||
function readS() {
|
function readByPW() {
|
||||||
var pw;
|
WScript.StdErr.Write('<<readByPW>>'); //_DBG_
|
||||||
// Microsoft Windows PowerShell https://technet.microsoft.com/ja-jp/library/hh847837.aspx
|
|
||||||
shellExec('powershell /?', function(exitCode, stdout, stderr, error) {
|
|
||||||
if (error || exitCode !== 0) {
|
|
||||||
pw = scriptPW();
|
|
||||||
} else {
|
|
||||||
shellExec('powershell -Command "$text = Read-Host -AsSecureString;' +
|
|
||||||
'$BSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($text);' +
|
|
||||||
'[System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR)"',
|
|
||||||
function(exitCode, stdout, stderr, error) {
|
|
||||||
if (error || exitCode !== 0) {
|
|
||||||
WScript.StdErr.WriteLine('Windows PowerShell Error: ' + exitCode +
|
|
||||||
(error && error.description ? '\n' + error.description : '') +
|
|
||||||
(stderr ? '\n' + stderr : '') +
|
|
||||||
(stdout ? '\n' + stdout : ''));
|
|
||||||
WScript.Quit(1);
|
|
||||||
}
|
|
||||||
pw = stdout.replace(/[\r\n]+$/, '');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return pw;
|
|
||||||
}
|
|
||||||
|
|
||||||
function scriptPW() {
|
|
||||||
var pw;
|
var pw;
|
||||||
// exit-code is not returned even if an error is thrown.
|
// exit-code is not returned even if an error is thrown.
|
||||||
try {
|
try {
|
||||||
|
@ -107,43 +112,9 @@ function getFso() {
|
||||||
return fso;
|
return fso;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getShell() {
|
|
||||||
if (!shell) { shell = WScript.CreateObject('WScript.Shell'); }
|
|
||||||
return shell;
|
|
||||||
}
|
|
||||||
|
|
||||||
function shellExec(cmd, callback) { // callback(exitCode, stdout, stderr, error)
|
|
||||||
var wsExec, stdout = '', stderr = '', noOutput;
|
|
||||||
|
|
||||||
try {
|
|
||||||
wsExec = getShell().Exec(cmd);
|
|
||||||
} catch (e) {
|
|
||||||
callback(e.number, stdout, stderr, e);
|
|
||||||
return wsExec;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (true) {
|
|
||||||
noOutput = true;
|
|
||||||
if (!wsExec.StdOut.AtEndOfStream) {
|
|
||||||
stdout += wsExec.StdOut.ReadAll();
|
|
||||||
noOutput = false;
|
|
||||||
}
|
|
||||||
if (!wsExec.StdErr.AtEndOfStream) {
|
|
||||||
stderr += wsExec.StdErr.ReadAll();
|
|
||||||
noOutput = false;
|
|
||||||
}
|
|
||||||
if (noOutput) {
|
|
||||||
if (wsExec.Status === 1 /*WshFinished*/) { break; }
|
|
||||||
WScript.Sleep(100);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
callback(wsExec.ExitCode, stdout, stderr);
|
|
||||||
return wsExec;
|
|
||||||
}
|
|
||||||
|
|
||||||
function decodeDOS(arg) {
|
function decodeDOS(arg) {
|
||||||
return (arg + '').replace(/#(\d+);/g, function(str, charCode) {
|
return arg.replace(/#(\d+);/g, function(str, charCode) {
|
||||||
return String.fromCharCode(+charCode);
|
return String.fromCharCode(+charCode);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
93
lib/read.ps1
Normal file
93
lib/read.ps1
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
|
||||||
|
Param(
|
||||||
|
[string] $display,
|
||||||
|
[switch] $noEchoBack,
|
||||||
|
[string] $mask = '*',
|
||||||
|
[switch] $keyIn,
|
||||||
|
[switch] $encoded
|
||||||
|
)
|
||||||
|
|
||||||
|
$ErrorActionPreference = 'Stop' # for cmdlet
|
||||||
|
trap {
|
||||||
|
# `throw $_` and `Write-Error $_` return exit-code 0
|
||||||
|
$Host.UI.WriteErrorLine($_)
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
function decodeDOS($arg) {
|
||||||
|
[Regex]::Replace($arg, '#(\d+);', { [char][int] $args[0].Groups[1].Value })
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($encoded) {
|
||||||
|
if ($display -ne '') { $display = decodeDOS $display }
|
||||||
|
if ($mask -ne '') { $mask = decodeDOS $mask }
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Warning "[PS] display: <$display>" #_DBG
|
||||||
|
Write-Warning "[PS] noEchoBack: $noEchoBack" #_DBG
|
||||||
|
Write-Warning "[PS] mask: <$mask>" #_DBG
|
||||||
|
Write-Warning "[PS] keyIn: $keyIn" #_DBG
|
||||||
|
|
||||||
|
# Instant method that opens TTY without CreateFile via P/Invoke in .NET Framework
|
||||||
|
# **NOTE** Don't include special characters in $command when $getRes is True.
|
||||||
|
function execWithTTY ($command, $getRes = $False) {
|
||||||
|
Write-Warning "[PS] command: <$command> getRes: $getRes" #_DBG
|
||||||
|
if ($getRes) {
|
||||||
|
$res = (cmd.exe /C "<CON powershell.exe -Command $command")
|
||||||
|
if ($LastExitCode -ne 0) { exit 1 }
|
||||||
|
} else {
|
||||||
|
$command | cmd.exe /C ">CON powershell.exe -Command -"
|
||||||
|
if ($LastExitCode -ne 0) { exit 1 }
|
||||||
|
$res = ''
|
||||||
|
}
|
||||||
|
return $res
|
||||||
|
}
|
||||||
|
|
||||||
|
function writeTTY ($text) {
|
||||||
|
execWithTTY ('Write-Host ''' + ($text -replace '''', '''''') + ''' -NoNewline')
|
||||||
|
}
|
||||||
|
|
||||||
|
[string] $inputTTY = ''
|
||||||
|
|
||||||
|
if ($noEchoBack -and (-not $keyIn) -and ($mask -eq '*')) {
|
||||||
|
$inputTTY = execWithTTY ('$inputTTY = Read-Host -AsSecureString;' +
|
||||||
|
'$bstr = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($inputTTY);' +
|
||||||
|
'[System.Runtime.InteropServices.Marshal]::PtrToStringAuto($bstr)') $True
|
||||||
|
return $inputTTY
|
||||||
|
}
|
||||||
|
|
||||||
|
$isEditable = (-not $noEchoBack) -and (-not $keyIn)
|
||||||
|
if ($keyIn) { $reqSize = 1 }
|
||||||
|
else { $reqSize = 1024 } # dummy
|
||||||
|
|
||||||
|
while ($True) {
|
||||||
|
if ($isEditable) {
|
||||||
|
$chunk = execWithTTY 'Read-Host' $True
|
||||||
|
$chunk += "`n"
|
||||||
|
} else { # raw
|
||||||
|
$chunk = execWithTTY '[System.Console]::ReadKey($True).KeyChar' $True
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($chunk -eq '') { break }
|
||||||
|
$chunk = $chunk -replace '[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]', ''
|
||||||
|
if ($chunk -eq '') { continue }
|
||||||
|
|
||||||
|
if (-not $isEditable) {
|
||||||
|
$displayInput = $chunk -replace '[\r\n]', ''
|
||||||
|
if ($displayInput -ne '') {
|
||||||
|
if ($noEchoBack) {
|
||||||
|
if ($mask -eq '') { $displayInput = '' }
|
||||||
|
else { $displayInput = $displayInput -replace '.', $mask }
|
||||||
|
}
|
||||||
|
if ($displayInput -ne '') { writeTTY $displayInput }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$inputTTY += $chunk
|
||||||
|
if (($inputTTY -match '[\r\n]$') -or ($keyIn -and ($inputTTY.Length -ge $reqSize)))
|
||||||
|
{ break }
|
||||||
|
}
|
||||||
|
|
||||||
|
if (-not $isEditable) { writeTTY "`n" } # new-line
|
||||||
|
|
||||||
|
return '''' + $inputTTY + '''' #DBG
|
|
@ -27,10 +27,10 @@ var
|
||||||
useExt = false,
|
useExt = false,
|
||||||
|
|
||||||
fdR = 'none', fdW, ttyR, isRawMode = false,
|
fdR = 'none', fdW, ttyR, isRawMode = false,
|
||||||
extHostPath, extScriptPath, tempdir, salt = 0;
|
extHostPath, extScriptPath, tempdir, salt = 0;
|
||||||
|
|
||||||
function readlineSync(options) { // display, mask are string
|
function readlineSync(options) { // display, mask are string
|
||||||
var input = '', isEditable, displayInput;
|
var input = '', displayTmp;
|
||||||
|
|
||||||
function tryExt() {
|
function tryExt() {
|
||||||
var res = readlineExt(options);
|
var res = readlineExt(options);
|
||||||
|
@ -38,14 +38,6 @@ function readlineSync(options) { // display, mask are string
|
||||||
return res.input;
|
return res.input;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Node v0.10- returns an error if same mode is set.
|
|
||||||
function setRawMode(mode) {
|
|
||||||
if (mode === isRawMode) { return true; }
|
|
||||||
if (ttyR.setRawMode(mode) !== 0) { return false; }
|
|
||||||
isRawMode = mode;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
var fsB, constants;
|
var fsB, constants;
|
||||||
|
|
||||||
|
@ -114,10 +106,22 @@ function readlineSync(options) { // display, mask are string
|
||||||
if (options.display !== '' && typeof print === 'function')
|
if (options.display !== '' && typeof print === 'function')
|
||||||
{ print(options.display, encoding); }
|
{ print(options.display, encoding); }
|
||||||
|
|
||||||
isEditable = !options.noEchoBack && !options.keyIn;
|
|
||||||
|
|
||||||
(function() { // try read
|
(function() { // try read
|
||||||
var buffer, reqSize, readSize, chunk;
|
var buffer, reqSize, readSize, chunk, isInputLine = false,
|
||||||
|
isEditable = !options.noEchoBack && !options.keyIn;
|
||||||
|
|
||||||
|
function writeTTY(text) {
|
||||||
|
fs.writeSync(fdW, text);
|
||||||
|
isInputLine = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Node v0.10- returns an error if same mode is set.
|
||||||
|
function setRawMode(mode) {
|
||||||
|
if (mode === isRawMode) { return true; }
|
||||||
|
if (ttyR.setRawMode(mode) !== 0) { return false; }
|
||||||
|
isRawMode = mode;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if (useExt || !ttyR ||
|
if (useExt || !ttyR ||
|
||||||
typeof fdW !== 'number' && (options.display !== '' || !isEditable)) {
|
typeof fdW !== 'number' && (options.display !== '' || !isEditable)) {
|
||||||
|
@ -126,7 +130,7 @@ function readlineSync(options) { // display, mask are string
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.display !== '') {
|
if (options.display !== '') {
|
||||||
fs.writeSync(fdW, options.display);
|
writeTTY(options.display);
|
||||||
options.display = '';
|
options.display = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -154,12 +158,12 @@ function readlineSync(options) { // display, mask are string
|
||||||
if ((chunk = chunk.replace(/[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]/g, '')) === '')
|
if ((chunk = chunk.replace(/[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]/g, '')) === '')
|
||||||
{ continue; }
|
{ continue; }
|
||||||
|
|
||||||
if (!isEditable && (displayInput = chunk.replace(/[\r\n]/g, '')) !== '') {
|
if (!isEditable && (displayTmp = chunk.replace(/[\r\n]/g, '')) !== '') {
|
||||||
if (options.noEchoBack) {
|
if (options.noEchoBack) {
|
||||||
displayInput = options.mask === '' ? '' :
|
displayTmp = options.mask === '' ? '' :
|
||||||
(new Array(displayInput.length + 1)).join(options.mask);
|
(new Array(displayTmp.length + 1)).join(options.mask);
|
||||||
}
|
}
|
||||||
if (displayInput !== '') { fs.writeSync(fdW, displayInput); }
|
if (displayTmp !== '') { writeTTY(displayTmp); }
|
||||||
}
|
}
|
||||||
|
|
||||||
input += chunk;
|
input += chunk;
|
||||||
|
@ -167,14 +171,14 @@ function readlineSync(options) { // display, mask are string
|
||||||
options.keyIn && input.length >= reqSize) { break; }
|
options.keyIn && input.length >= reqSize) { break; }
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isEditable) { fs.writeSync(fdW, '\n'); }
|
if (!isEditable && !(options.keyIn && !isInputLine)) { writeTTY('\n'); }
|
||||||
setRawMode(false);
|
setRawMode(false);
|
||||||
})();
|
})();
|
||||||
|
|
||||||
if (typeof print === 'function') {
|
if (typeof print === 'function') {
|
||||||
displayInput = input.replace(/[\r\n]/g, '');
|
displayTmp = input.replace(/[\r\n]/g, '');
|
||||||
print((options.noEchoBack ?
|
print((options.noEchoBack ?
|
||||||
(new Array(displayInput.length + 1)).join(options.mask) : displayInput) +
|
(new Array(displayTmp.length + 1)).join(options.mask) : displayTmp) +
|
||||||
'\n', encoding);
|
'\n', encoding);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue