Мне нужно программно переместить позицию курсора терминала с помощью NodeJS. Я использую process.stdout.moveCursor(x, y) , который отлично работает с обычными символами ASCII шириной в 1 символ.
Однако это не работает с более длинными символами EAST ASIAN WIDTH
, такими как китайские иероглифы, японские иероглифы и полноразмерные английские символы. Например, width
по сравнению с width
, если я сдвину каретку на 1 единицу вправо, позиция каретки окажется в середине h
, в результате чего каретка даже не появится в терминалах Windows.
Несмотря на то, что я мог бы отслеживать ширину каждого отдельного символа и выполнять вычисления, как показано ниже, я чувствую, что должен быть способ перемещать курсор на основе целых символов, а не на основе какой-либо единицы x
, которая находится в moveCursor
(поскольку естественно, нажатие стрелки влево в терминале приведет к правильному перемещению курсора.)
process.stdout.write("Test data! 測試資料123テスト");
/* to move caret 5 characters from the right requires
the following value to get the correct result */
const offsetRight = 3 * -1 + 2 * -2;
process.stdout.moveCursor(offsetRight, 0);
Примечание. Я использую последнюю версию nodeJS, и программа в основном работает с командной строкой Windows 10/11. Однако я тестировал его на Ubuntu и WSL, и у обоих одна и та же проблема.
🤔 А знаете ли вы, что...
С Node.js можно создавать приложения, работающие в режиме реального времени, такие как чаты и игры.
Одно из решений, которое я нашел, — проявить творческий подход с помощью escape-кода «Сохранить/восстановить текущую позицию курсора» ANSI escape-кода . Однако я полагаю, что это решение работает только для терминалов ANSI.
Курсор вперед (\x1b[nC
) и курсор назад (\x1b[n
) имеют ту же проблему, что описана в вопросе, поскольку она все еще зависит от преобразования символов X в единицы ячейки ширины Y. Вместо этого функция «Сохраненная позиция курсора» работает правильно, поскольку она отражает абсолютную позицию ячеек курсора независимо от того, есть ли более широкие символы с широкими несколькими ячейками или нет.
const test = "Test data! 測試資料123テスト";
const offsetRight = 3; //Cursor should stop right after '123'
process.stdout.write(test.slice(0, test.length - offsetRight));
process.stdout.write('\x1b[s'); //Save cursor position
process.stdout.write(test.slice(test.length - offsetRight));
process.stdout.write('\x1b[u'); //Restore cursor position