Node.js 捕捉击键的节点脚本不';被shell脚本调用时无法工作
因此,我有一个node.js脚本,可以捕获用户在终端中的击键。当我从命令行调用它时,它工作得很好,但是当我从bash脚本(git pre-commit)调用脚本时,一切都正常,直到用户输入阶段,程序将无法拾取输入 我还应该提到我现在在windows上使用git bash作为shell node.js脚本的代码:Node.js 捕捉击键的节点脚本不';被shell脚本调用时无法工作,node.js,bash,Node.js,Bash,因此,我有一个node.js脚本,可以捕获用户在终端中的击键。当我从命令行调用它时,它工作得很好,但是当我从bash脚本(git pre-commit)调用脚本时,一切都正常,直到用户输入阶段,程序将无法拾取输入 我还应该提到我现在在windows上使用git bash作为shell node.js脚本的代码: const fs = require('fs'); const path = require('path'); const readline = require('readline');
const fs = require('fs');
const path = require('path');
const readline = require('readline');
const regedit = require('regedit');
const { bufferStringToString } = require("./functions")
const scriptArgs = process.argv.slice(2)
let spawn = getExtendedSpawn();
function getExtendedSpawn() {
var childProcess = require("child_process");
var oldSpawn = childProcess.spawn;
function mySpawn() {
console.log('spawn called');
console.log(arguments);
var result = oldSpawn.apply(this, arguments);
return result;
}
return mySpawn;
};
//prevents node from exiting
setInterval(function() {
console.log("Are you still there?");
}, 1000 * 60 * 60);
//directory build commands will be run in
const projectRoot = path.resolve(__dirname, "../../..", "portfolio.chriscormier.ca");
function validateWindowsEnviroment() {
regedit.list('HKCU\\Environment', function (err, result) {
const
firstKey = Object.keys(result)[0],
pathVarValue = result[firstKey].values.Path.value,
individualPathItems = pathVarValue.split(";");
if (individualPathItems.includes('C:\\windows\\system32') === false) {
console.error(["\n",
" ",
"it seems to be the first time you've used this script on this windows machine.\n",
" ",
"The enviroment variable \'Path\' doesn't have an entry for 'C:\\windows\\system32.\n",
" ",
"Add the value 'C:\\windows\\system32;' in the regeistry to use this script.\n",
" ",
"P.S.Don't forget you need to do a system restart after a regeistry change.\n"
].join(""))
} else if (individualPathItems.includes('C:\\windows\\system32')) {
return
}
})
}
function changeDir(path) {
try {
process.chdir(path)
} catch (err) {
console.error( "ERROR: Path to project root is invalid. This source file was likley moved. To fix, update this file's 'projectRoot' constant" + "\n")
console.error(err.message, err.stack)
process.exit(1)
}
}
let processesExited = 0;
async function runCmd(rawCommand) {
//if agument passed has no spaces, then it wouldn't have an args
let commandToRun;
let isMultiArgCommand = rawCommand.search(" ") !== -1
let commandArgs = [];
let trimmedCommand;
if (isMultiArgCommand === true) {
//changes a command like "npm run start" to npm run start
const paddedWithSingleQs = (rawCommand.search("\'") !== -1) ? true : false;
const paddedWithDoubleQs = ( rawCommand.search("\"") !== -1 ) ? true : false;
const paddedWith = (paddedWithSingleQs) ? "\'" : "\"";
trimmedCommand = rawCommand.replace(new RegExp(paddedWith, "g"), "")
//splits command arguments and quoted arguments from main command
const quotesOfNestedArgs = ( paddedWith === '\'' ) ? '\"': '\''
const forFindingNestedArgs = new RegExp(`${quotesOfNestedArgs}\w+?${quotesOfNestedArgs}`, "g")
const
commandWithMultiPlaceholders = trimmedCommand
quotedArgs = trimmedCommand.match(forFindingNestedArgs)
hasNestedArgs = quotedArgs !== null
let properlyQuotedArgs;
if (hasNestedArgs === true) {
properlyQuotedArgs = ( quotesOfNestedArgs === '\'' ) ? quotedArgs.replace(/'/g,'\"') : quotedArgs
}
commandArgs = commandArgs.concat(properlyQuotedArgs)
}
let child;
if (isMultiArgCommand === true) {
child = spawn(rawCommand, { shell:true } );
} else if ( isMultiArgCommand === false ) {
child = spawn(trimmedCommand, commandArgs, { shell:true } );
}
//error logging
const errorBuffer = [];
child.stderr.on('data', (chunk) => {
errorBuffer.concat(chunk)
})
child.stderr.on('end', () => {
const errorContent = Buffer.concat(errorBuffer).toString();
console.error(errorContent)
})
// use child.stdout.setEncoding('utf8'); if you want text chunks
child.stdout.on('data', (chunk) => {
const chunckAsText = bufferStringToString(chunk)
console.log(chunckAsText)
});
child.on('close', (code) => {
++processesExited
return
});
}
let counter = 0
function runCommands(cmdsArray) {
cmdsArray.forEach(cmd => {
++counter
console.log("ran one command")
runCmd(cmd)
});
}
//------------------ main execution -----------------------
validateWindowsEnviroment()
//changes working directory to C:\Users\chris\Google Drive\code projects\portfolio.chriscormier.ca
changeDir(projectRoot)
console.log("\n Add Build to Staging? (Y/n)")
//------------------ reation after keypress answer -----------------------
readline.emitKeypressEvents(process.stdin);
if (process.stdin.isTTY) {
process.stdin.setRawMode(true);
}
const onKeyPress = (key, keypressData) => {
if (keypressData.ctrl && keypressData.name === 'c') {
process.exit();
} else {
if (keypressData.name === 'y' || keypressData.name === 'return') {
runCommands(scriptArgs)
const interval = setInterval(() => {
if (processesExited === scriptArgs.length) {
runCmd("git add build")
.then(() => {
clearInterval(interval)
console.log("\n Added Build to Index\n")
process.exit()
})
}
},70)
} else if (keypressData.name === 'n') {
process.exit()
}
}
}
process.stdin.on('keypress', onKeyPress);
包装节点脚本的bash脚本中的代码:
#!/bin/sh
foundProjectDir=""
for i in {1..5}
do
cd ..
foundProjectDir='find . -type d -name 'portfolio.chriscormier.ca''
if [ -n "$($foundProjectDir)" ]
then
cd "$($foundProjectDir)"
echo "Navigated to project root at $(pwd)"
break
fi
done
node ./scripts/ask-to-run-build/ask-to-run-build.js "gulp build"
我从未在node中处理过输入流,所以idk(如果这是node的常见问题/限制)。任何建议都有帮助