2009-06-26 12 views
7

Estoy escribiendo un filtro (en una tubería destinada a una salida del terminal) que a veces necesita "sobrescribir" una línea que acaba de ocurrir. Funciona pasando stdin a stdout carácter por carácter hasta llegar a \n, y luego invocando un comportamiento especial. Mi problema es cómo volver al comienzo de la línea.Devolución del cursor del terminal al inicio de línea con el ajuste habilitado

Lo primero que pensé fue utilizar una secuencia \r o ANSI \033[1G. Sin embargo, si la línea fue lo suficientemente larga como para haber envuelto el terminal (y por lo tanto provocó que se desplace), estos solo moverán el cursor nuevamente a la línea física actual.

Mi segunda idea fue seguir la longitud de la línea (número de caracteres pasados ​​desde la anterior \n), y luego echo \b que muchas veces. Sin embargo, eso no funciona si la línea contenía caracteres de control o secuencias de escape (¿y posiblemente Unicode?).

A falta de buscar todas las secuencias especiales y usar esto para ajustar el recuento de caracteres, ¿hay una manera simple de lograr esto?

Respuesta

0

Puede consultar dimensiones del terminal con un simple 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 

De esta manera se puede evitar la impresión nada más allá del final de la línea y simplemente usar el método \r.

+0

Gracias por la sugerencia! Lamentablemente, hay un par de razones por las que no creo que eso funcione para mí: * Todavía necesitaría seguir secuencias de casos especiales para saber qué tan cerca del límite estoy * Puede que no sea lo último en la tubería Por contexto; mi filtro es coincidencia de patrones, y "reescribe" cadenas coincidentes rodeadas de secuencias de escape de color. No puedo usar 'fgets()' y operar cadenas enteras a la vez, ya que parte de mi entrada producirá una salida "dinámica" (por ejemplo, un estado de progreso creciente) que no da salida '\ n' por un tiempo. –

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!!!! ....................................... 
...................................................... 

buscar la save_cursor y restore_cursor características de cadena en la base de datos terminfo.

+0

Según tengo entendido, rc y sc guardan la ubicación * física * del cursor (equivalente a \ 033 [sy \ 033 [u)]. Si todo el contenido del terminal se desplaza debido al ajuste de línea, el comienzo de la cadena ya no se encuentra en la misma posición física. (Al menos, este es el comportamiento que observo en xterm.) –

+0

Ah, eso parece suceder en mi terminal también. Aww ... – ephemient

4

Incluso si hubiera una "secuencia mágica" que cuando se escribe en una consola borre de manera confiable la última línea escrita, TODAVÍA obtendría la línea y la secuencia en la salida (aunque esté oculta en una consola). ¿Piensa qué pasaría si alguien escribiera el resultado en un archivo, o lo pasara a otros filtros? ¿Sabrían ellos cómo manejar tal entrada? Y no me digas que descartas la posibilidad de escribir en otro lugar que no sea directamente en una consola. Tarde o temprano, alguien querrá redirigir la salida, ¡incluso usted!

La forma correcta de hacer esto es almacenar cada línea en la memoria mientras se procesa, y luego decidir si la genera o no. Realmente no hay forma de evitar esto.

+0

De hecho, esa fue mi solución original. El único lugar que se rompe es para cosas tales como un porcentaje de progreso que se incrementa con el tiempo (sobrescribiéndose con \ b), donde no hay \ n durante varios segundos o minutos, por lo que fgets() y así sucesivamente bloquean durante un período considerable.Incidentalmente, he descartado la posibilidad de que mi filtro no sea lo último en la tubería (a pesar de lo que dije en un comentario anterior), ¡ya que no hay razón para usarlo más que como una herramienta para embellecer la salida de la consola! –

+0

Un comentario rápido sobre ser el último elemento en la tubería: ¿no puedes asegurarte de que stdout va a una terminal, como lo hace 'ls'? –

Cuestiones relacionadas