2009-06-26 2 views
7

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

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

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

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

ответ

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.

+0

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

0
 
$ 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

Я понимаю, что rc и sc сохраняют * физическое * местоположение курсора (эквивалентно \ 033 [s и \ 033 [u). Если весь контент терминала прокручивается из-за обертки строки, начало строки больше не находится в том же физическом положении. (По крайней мере, это поведение, которое я наблюдаю в xterm.) –

+0

А, похоже, это происходит и в моем терминале. Aww ... – ephemient

4

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

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

+0

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

+0

Быстрый комментарий о последнем элементе в трубе: не можете ли вы убедиться, что stdout отправляется на терминал, как 'ls' делает? –

Смежные вопросы