我正在尝试获取 Nodejs 应用程序中的当前光标位置。
我已经尝试过
getCursorPos
(https://nodejs.org/api/readline.html#rlgetcursorpos),但它返回输入提示的相对位置,行的值是0
我能够使用下面的答案创建一个获取此信息的承诺,其中包含用于请求终端光标位置的转义序列:
const getCursorPos = () => new Promise((resolve) => {
const termcodes = { cursorGetPosition: '\u001b[6n' };
process.stdin.setEncoding('utf8');
process.stdin.setRawMode(true);
const readfx = function () {
const buf = process.stdin.read();
const str = JSON.stringify(buf); // "\u001b[9;1R"
const regex = /\[(.*)/g;
const xy = regex.exec(str)[0].replace(/\[|R"/g, '').split(';');
const pos = { rows: xy[0], cols: xy[1] };
process.stdin.setRawMode(false);
resolve(pos);
}
process.stdin.once('readable', readfx);
process.stdout.write(termcodes.cursorGetPosition);
})
const AppMain = async function () {
process.stdout.write('HELLO');
const pos = await getCursorPos();
process.stdout.write("\n");
console.log({ pos });
}
AppMain();
使用控制台代码的手册页和tty的节点文档我们可以构建更强大的getCursorPos函数版本:
function getCursorPos() {
return new Promise((resolve, reject) => {
// stdout has to be a tty for this
if (!process.stdout.isTTY) return reject(new Error('not a tty'));
// get the current raw-mode to restore it later
const prevRawMode = process.stdin.isRaw;
// stdin must be in raw-mode to emit the result without user interaction
process.stdin.setRawMode(true);
// use the data event, because stdin is a socket
process.stdin.once('data', (data) => {
try {
// restore the previous raw-mode
process.stdin.setRawMode(prevRawMode);
// get the answer as string for the regex matching
const answer = Buffer.isBuffer(data) ? data.toString() : data;
// get the row and column of the cursor with the specified pattern
const match = /\x1B\[(?<column>\d+);(?<row>\d+)R/.exec(answer);
if (!match) throw new Error('position not found');
// convert to 0-based coordinates
resolve({
x: Number(match.groups.row) - 1,
y: Number(match.groups.column) - 1
});
} catch (err) {
reject(err);
}
});
// write the CPR-sequence (cursor position report) to stdout
// to trigger the position request
process.stdout.write('\x1B[6n');
});
}