如何使用nodejs readline获取相对于输出的当前光标位置

问题描述 投票:0回答:2

我正在尝试获取 Nodejs 应用程序中的当前光标位置。

我已经尝试过

getCursorPos
https://nodejs.org/api/readline.html#rlgetcursorpos),但它返回输入提示的相对位置,行的值是
0

javascript node.js command-line-interface readline console.log
2个回答
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();

0
投票

使用控制台代码的手册页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');
    });
}

© www.soinside.com 2019 - 2024. All rights reserved.