Вопрос по c, terminal, linux – Возврат терминального курсора в начало строки с включенным переносом

7

Я пишу фильтр (в канале, предназначенном для вывода терминала), который иногда должен «перезаписывать»; линия, которая только что произошла. Это работает, передавая стандартный ввод в стандартный вывод до тех пор, пока\n достигается, а затем вызывает особое поведение. Моя проблема касается того, как вернуться к началу строки.

Первое, о чем я подумал, это использовать\r или последовательность ANSI\033[1G, Однако, если строка была достаточно длинной для переноса на терминал (и, следовательно, заставила ее прокручиваться), они будут только перемещать курсор назад к текущемуphysical линия.

Моя вторая идея заключалась в том, чтобы отслеживать длину строки (количество символов, переданных с момента предыдущего\n), а затем эхо\b это много раз. Однако, это пойдет не так, если строка содержит управляющие символы или escape-последовательности (и, возможно, Unicode?).

Если не считать всех специальных последовательностей и не использовать их для настройки количества символов, есть ли простой способ добиться этого?

Ваш Ответ

3   ответа
1
$ cat >test.sh <<'EOF'
> #!/bin/sh
> tput sc
> echo 'Here is a really long multi-line string: .............................................................................................'
> tput rc
> echo 'I went back and overwrote some stuff!!!!'
> echo
> EOF
$ sh test.sh
I went back and overwrote some stuff!!!! .......................................
......................................................

save_cursor а такжеrestore_cursor строковые возможности вterminfo база данных.

Ах, похоже, это происходит и в моем терминале. Оо ...
Я понимаю, что rc и sc сохраняютphysical расположение курсора (эквивалентно \ 033 [с и \ 033 [и)). Если весь контент терминала прокручивается из-за переноса строки, начало строки больше не находится в той же физической позиции. (По крайней мере, такое поведение я наблюдаю в xterm.) Oliver Charlesworth
0

ioctl:

#include <sys/types.h>
#include <sys/ioctl.h>

// ...

struct winsize ws;
ioctl(1, TIOCGWINSZ, &ws);

// ws.ws_col, ws.ws_row should now contain terminal dimensions

Таким образом, вы можете предотвратить печать чего-либо за пределами строки и просто использовать\r метод.

Спасибо за предложение! К сожалению, есть несколько причин, по которым я не думаю, что это сработает для меня: * Мне все равно нужно отслеживать последовательности в особых случаях, чтобы знать, насколько я близок к краю * Возможно, я не последняя вещь в конвейере Для контекста; мой фильтр сопоставлен с шаблоном и "переписывает" соответствующие строки, окруженные цветными escape-последовательностями. Я не могу использоватьfgets() и работать с целыми строками за раз, так как некоторые из моих входных данных приведут к «динамическому» вывод (например, прогрессирующее состояние прогресса), который не выводит\n какое-то время. Oliver Charlesworth
4

оль надежно удалит последнюю записанную строку, вы ЕЩЕ ПОЛУЧИТЕ строку и последовательность на выходе (хотя и скрытые на консоли). Подумайте, что произойдет, если кто-нибудь запишет вывод в файл или передаст его по трубе другим фильтрам? Будут ли они знать, как обрабатывать такой ввод? И не говорите мне, что вы исключаете возможность записи в другое место, кроме как непосредственно на консоль. Рано или поздно кто-то захочет перенаправить вывод - может быть, даже вы!

Правильный способ сделать это состоит в том, чтобы буферизовать каждую строку в памяти по мере ее обработки, а затем решить, выводить ее или нет. Там действительно нет никакого способа обойти это.

Краткий комментарий о том, что последний элемент в конвейере: не можете ли вы убедиться, что стандартный вывод идет в терминал, так какls делает?
Действительно, это было мое первоначальное решение. Единственное место, которое ломается, это такие вещи, как процент выполнения, который увеличивается с течением времени (перезаписывая себя с помощью \ b), где нет \ n в течение нескольких секунд или минут, поэтому fgets () и т. Д. Блокируются в течение значительного периода времени. Между прочим, я обесценил возможность того, что мой фильтр не является последним в конвейере (несмотря на то, что я сказал в предыдущем комментарии), так как нет причин использовать его, кроме как в качестве инструмента для предварительного вывода результатов консоли! Oliver Charlesworth

Похожие вопросы