2009-06-26 9 views
7

sto scrivendo un filtro (in un tubo destinato ad un'uscita del terminale) che a volte ha bisogno di "sovrascrivere" una linea che è appena avvenuto. Funziona passando lo stdin allo stdout carattere per carattere fino a quando viene raggiunto un valore \n e quindi si richiama un comportamento speciale. Il mio problema riguarda come tornare all'inizio della linea.il cursore terminale per lanciare-di-linea con lo spostamento abilitato

La prima cosa che ho pensato è stata l'utilizzo di \r o la sequenza ANSI \033[1G. Tuttavia, se la linea era sufficientemente lunga da essere avvolta nel terminale (e quindi provocato lo scorrimento), questi spostano solo il cursore sulla linea fisica corrente.

La mia seconda idea era quella di tracciare la lunghezza della linea (numero di caratteri passati dal precedente \n), quindi echo \b più volte. Tuttavia, ciò non funziona se la riga contiene caratteri di controllo o sequenze di escape (e possibilmente Unicode?).

corta di ricerca di tutte le sequenze speciali e l'utilizzo di questo per regolare il mio conteggio dei caratteri, c'è un modo semplice per raggiungere questo obiettivo?

risposta

0

È possibile interrogare le dimensioni del terminale con un semplice 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 

questo modo si può evitare che la stampa nulla oltre alla fine della linea e semplicemente utilizzare il metodo \r.

+0

Grazie per il suggerimento! Purtroppo ci sono un paio di motivi per cui non penso che funzionerà per me: * Avrei ancora bisogno di monitorare le sequenze del caso speciale per sapere quanto vicino al limite sono * Potrei non essere l'ultima cosa in la pipeline Per contesto; il mio filtro è pattern matching e "riscrittura" di stringhe corrispondenti circondate da sequenze di escape a colori. Non posso usare 'fgets()' e operare su intere stringhe alla volta, dato che alcuni dei miei input produrranno un output "dinamico" (ad esempio uno stato di avanzamento incrementale) che non emette '\ n' per un po '. –

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

Cerca gli funzionalità save_cursor e restore_cursor stringa nel database terminfo.

+0

La mia comprensione è che rc e sc salvano la posizione * fisica * del cursore (equivalente a \ 033 [s e \ 033 [u). Se l'intero contenuto del terminale scorre a causa del line-wrap, l'inizio della stringa non si trova più nella stessa posizione fisica. (Almeno, questo è il comportamento che osservo in xterm.) –

+0

Ah, sembra che capiti anche nel mio terminale. Aww ... – ephemient

4

Anche se ci fosse una "sequenza magica" che quando si scrive su una console cancella in modo affidabile l'ultima riga scritta, si otterrebbe ANCORA la linea e la sequenza sull'output (benché nascosta su una console). Pensa a cosa accadrebbe se qualcuno scrivesse l'output su un file o lo passasse in pipe ad altri filtri? Saprebbero come gestire tale input? E non dirmi che escludi la possibilità di scrivere da qualche altra parte direttamente su una console. Prima o poi qualcuno vorrà reindirizzare l'output, forse anche tu!

Il modo giusto per eseguire questa operazione consiste nel bufferare ogni riga in memoria mentre viene elaborata e quindi decidere se emetterla o meno. Non c'è davvero alcun modo per aggirare questo.

+0

In effetti, quella era la mia soluzione originale. L'unico posto che si interrompe è per cose come una percentuale di progresso che si incrementa nel tempo (sovrascrivendo se stessa con \ b), dove non c'è \ n per diversi secondi o minuti, quindi fgets() e così via per un periodo considerevole.Per inciso, ho scartato la possibilità che il mio filtro non sia l'ultima cosa nella pipeline (nonostante quello che ho detto in un commento precedente), poiché non c'è motivo di usarlo se non come strumento per migliorare l'output della console! –

+0

Un rapido commento sull'essere l'ultimo oggetto nella pipe: non puoi assicurarti che stdout vada a un terminale, come fa 'ls'? –