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
|
||||
FSO_ForReading = 1, FSO_ForWriting = 2,
|
||||
|
||||
fso, tty, shell,
|
||||
fso, tty,
|
||||
args =// Array.prototype.slice.call(WScript.Arguments),
|
||||
(function() {
|
||||
var args = [], i, iLen;
|
||||
for (i = 0, iLen = WScript.Arguments.length; i < iLen; i++) {
|
||||
args.push(WScript.Arguments(i));
|
||||
}
|
||||
for (i = 0, iLen = WScript.Arguments.length; i < iLen; i++)
|
||||
{ args.push(WScript.Arguments(i)); }
|
||||
return args;
|
||||
})(),
|
||||
arg, options = {};
|
||||
|
||||
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;
|
||||
} else if (arg === '--mask') {
|
||||
options.mask = args.shift();
|
||||
} else if (arg === '--keyin') {
|
||||
options.keyIn = true;
|
||||
} else if (arg === '--display') {
|
||||
options.display = args.shift();
|
||||
} else if (arg === '--encoded') {
|
||||
options.encoded = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof options.display === 'string' && options.display !== '') {
|
||||
writeTTY(options.encoded ? decodeDOS(options.display) : options.display);
|
||||
if (options.encoded) {
|
||||
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();
|
||||
|
||||
|
@ -46,6 +54,27 @@ function writeTTY(text) {
|
|||
}
|
||||
|
||||
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;
|
||||
try {
|
||||
text = getFso().OpenTextFile('CONIN$', FSO_ForReading).ReadLine();
|
||||
|
@ -57,32 +86,8 @@ function readTTY() {
|
|||
return text;
|
||||
}
|
||||
|
||||
function readS() {
|
||||
var pw;
|
||||
// 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() {
|
||||
function readByPW() {
|
||||
WScript.StdErr.Write('<<readByPW>>'); //_DBG_
|
||||
var pw;
|
||||
// exit-code is not returned even if an error is thrown.
|
||||
try {
|
||||
|
@ -107,43 +112,9 @@ function getFso() {
|
|||
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) {
|
||||
return (arg + '').replace(/#(\d+);/g, function(str, charCode) {
|
||||
return arg.replace(/#(\d+);/g, function(str, 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,
|
||||
|
||||
fdR = 'none', fdW, ttyR, isRawMode = false,
|
||||
extHostPath, extScriptPath, tempdir, salt = 0;
|
||||
extHostPath, extScriptPath, tempdir, salt = 0;
|
||||
|
||||
function readlineSync(options) { // display, mask are string
|
||||
var input = '', isEditable, displayInput;
|
||||
var input = '', displayTmp;
|
||||
|
||||
function tryExt() {
|
||||
var res = readlineExt(options);
|
||||
|
@ -38,14 +38,6 @@ function readlineSync(options) { // display, mask are string
|
|||
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() {
|
||||
var fsB, constants;
|
||||
|
||||
|
@ -114,10 +106,22 @@ function readlineSync(options) { // display, mask are string
|
|||
if (options.display !== '' && typeof print === 'function')
|
||||
{ print(options.display, encoding); }
|
||||
|
||||
isEditable = !options.noEchoBack && !options.keyIn;
|
||||
|
||||
(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 ||
|
||||
typeof fdW !== 'number' && (options.display !== '' || !isEditable)) {
|
||||
|
@ -126,7 +130,7 @@ function readlineSync(options) { // display, mask are string
|
|||
}
|
||||
|
||||
if (options.display !== '') {
|
||||
fs.writeSync(fdW, options.display);
|
||||
writeTTY(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, '')) === '')
|
||||
{ continue; }
|
||||
|
||||
if (!isEditable && (displayInput = chunk.replace(/[\r\n]/g, '')) !== '') {
|
||||
if (!isEditable && (displayTmp = chunk.replace(/[\r\n]/g, '')) !== '') {
|
||||
if (options.noEchoBack) {
|
||||
displayInput = options.mask === '' ? '' :
|
||||
(new Array(displayInput.length + 1)).join(options.mask);
|
||||
displayTmp = options.mask === '' ? '' :
|
||||
(new Array(displayTmp.length + 1)).join(options.mask);
|
||||
}
|
||||
if (displayInput !== '') { fs.writeSync(fdW, displayInput); }
|
||||
if (displayTmp !== '') { writeTTY(displayTmp); }
|
||||
}
|
||||
|
||||
input += chunk;
|
||||
|
@ -167,14 +171,14 @@ function readlineSync(options) { // display, mask are string
|
|||
options.keyIn && input.length >= reqSize) { break; }
|
||||
}
|
||||
|
||||
if (!isEditable) { fs.writeSync(fdW, '\n'); }
|
||||
if (!isEditable && !(options.keyIn && !isInputLine)) { writeTTY('\n'); }
|
||||
setRawMode(false);
|
||||
})();
|
||||
|
||||
if (typeof print === 'function') {
|
||||
displayInput = input.replace(/[\r\n]/g, '');
|
||||
displayTmp = input.replace(/[\r\n]/g, '');
|
||||
print((options.noEchoBack ?
|
||||
(new Array(displayInput.length + 1)).join(options.mask) : displayInput) +
|
||||
(new Array(displayTmp.length + 1)).join(options.mask) : displayTmp) +
|
||||
'\n', encoding);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue