Возврат терминального курсора в начало строки с включенным переносом - PullRequest
7 голосов
/ 26 июня 2009

Я пишу фильтр (в канале, предназначенном для вывода терминала), который иногда должен "перезаписать" только что возникшую строку. Он работает, передавая stdin символьному символу stdout до тех пор, пока не будет достигнут \n, и затем вызывает специальное поведение. Моя проблема касается того, как вернуться к началу строки.

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

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

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

Ответы [ 3 ]

4 голосов
/ 30 июня 2009

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

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

2 голосов
/ 26 июня 2009
$ 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.

0 голосов
/ 26 июня 2009

Вы можете запросить размеры терминала с помощью простого 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.

...