Impedire il lampeggiamento del testo / dello schermo quando si cancella


11

La mia sceneggiatura fa qualcosa del tipo:

while :;
   clear

   do_a_lot_of_output_here

   sleep 1
done

C'è qualche opzione per evitare che lo schermo lampeggi quando eseguo la cancellazione e l'output? Voglio farlo come al watchcomando (ma è scritto in C). Qualche consiglio?

clear | hexdump -C

00000000  1b 5b 48 1b 5b 32 4a                              |.[H.[2J|
00000007

PS. Sto bashsolo usando .


Puoi aggiungere l'output del tuo clear | hexdump -C?
ott--

Ho ampliato la domanda.
Ravnur,

Ho trovato un'altra soluzione su stackoverflow.com/questions/5367068/… - echo -en "\ec"lampeggia anche?
ott--

Ho trovato anche questo. Anche entrambe le varianti della risposta lampeggiano.
Ravnur,

Ho avuto successo con questo strumento: eccesso.org/article/2009/07/watch1-bash-unicode
raine

Risposte:


8

Il lampeggiamento si verifica perché lo script cancella l'intero schermo. Se dipinge sul testo esistente e cancella solo se necessario, non ci sarà sfarfallio.

Ecco un esempio:

#!/bin/sh
watchit() {
    HOME=$(tput cup 0 0)
    ED=$(tput ed)
    EL=$(tput el)
    ROWS=$(tput lines)
    COLS=$(tput cols)
    printf '%s%s' "$HOME" "$ED"
    while true
    do
        CMD="$@"
        ${SHELL:=sh} -c "$CMD" | head -n $ROWS | while IFS= read LINE; do
            printf '%-*.*s%s\n' $COLS $COLS "$LINE" "$EL"
        done
        printf '%s%s' "$ED" "$HOME"
        sleep 1
    done
}

watchit top -b -n 1

Lo fa:

  • stampa l'output dal comando dato che si adatta allo schermo (nessun avvolgimento o scorrimento)
  • scrive su righe esistenti, cancellando la parte di ciascuna riga che non viene sovrascritta
  • utilizza la edcapacità del terminale per stampare dalla posizione corrente alla fine dello schermo.

Se desideri gestire uno schermo ridimensionabile, puoi spostare le assegnazioni all'interno ROWSe COLSall'interno del loop esterno, ad es.

#!/bin/sh
watchit() {
    HOME=$(tput cup 0 0)
    ED=$(tput ed)
    EL=$(tput el)
    printf '%s%s' "$HOME" "$ED"
    while true
    do
        ROWS=$(tput lines)
        COLS=$(tput cols)
        CMD="$@"
        ${SHELL:=sh} -c "$CMD" | head -n $ROWS | while IFS= read LINE; do
            printf '%-*.*s%s\n' $COLS $COLS "$LINE" "$EL"
        done
        printf '%s%s' "$ED" "$HOME"
        sleep 1
    done
}

watchit top -b -n 1

perché tputchiede l'attuale dimensione dello schermo dal sistema.

Ulteriori letture:


1
Per coloro che usano #!/bin/bashe desiderano utilizzare watchitincorporato in un piccolo script autonomo con alcune funzioni, puoi farlo export -f function_name; watchit function_name.
aggregate1166877,

Questo ha funzionato perfettamente per me, tranne per il fatto che mi sono imbattuto in problemi divertenti nella parte superiore dello schermo, in cui le cose si spostavano e diventavano glitch per pezzi di testo più lunghi (qualsiasi cosa venga accorciata head). Sembra che il problema sia un errore off-by-one (almeno nella mia configurazione - sessione ssh in riquadri divisi, iTerm2) durante il calcolo del numero di righe. ROWS=`expr $(tput lines) - 1`affrontato perfettamente questo.
ohruunuruus,

Questo è meraviglioso, grazie mille @ thomas-dickey.
mbarkhau,

9

Un modo per evitare il lampeggiamento è ottenere tutto l'output prima di cancellare lo schermo in modo che ci sia un tempo minimo tra la cancellazione e il ridisegno. Questo è simile al concetto di doppio buffering:

while :; do
   output=$(do_a_lot_of_output_here)
   clear
   echo "$output"
   sleep 1
done

Questo non elimina completamente lo sfarfallio, ma accade significativamente meno frequentemente nella mia esperienza.


Il doppio buffering, proprio come in qualsiasi altra situazione,
salva

Ha funzionato come un fascino. Nessuno sfarfallio :)
Lars Juel Jensen,

1
Lo sfarfallio rimanente può essere eliminato includendo il clearnel buffer, ovvero output=$(clear; do_a_lot_of_output_here).
kdb,

@kdb Bel suggerimento! Questo quasi completamente elimina lo sfarfallio per me ed è molto più semplice della risposta accettata.
Michael Mior,

Funziona come un incantesimo! All'inizio ho perso le virgolette doppie nell'eco "$ output" ', e poi le righe sono confuse. (Tutti gli spazi bianchi sono considerati spazi singoli.)
Popup

5

Il lampeggiamento è un risultato inevitabile dell'azzeramento dello schermo ogni volta attorno al loop. È possibile spostare il cursore nella parte superiore dello schermo e sovrascrivere invece parti del vecchio output.

# You may want to do this if your code is in a script.
unhide_cursor() {
    printf '\e[?25h'
}
trap unhide_cursor EXIT

# Hide the cursor (there is probably a much better way to do this)
printf '\e[?25l'
clear 
while true ; do
    # Move the cursor to the top of the screen but don't clear the screen
    printf '\033[;H' 
    do_a_lot_of_output_here
    sleep 1
done

Questo script lascerà artefatti se l'output si restringe. Inoltre, non è molto probabile che sia portatile. L'ho provato solo con urxvt, xterm e st.


In questo caso il cursore inizia a saltare fino alla fine dell'output da una posizione casuale (e naturalmente gli artefatti). Inoltre ho provato tput clearcon gli stessi risultati (
battendo le

Ho aggiunto un paio di righe allo script per nascondere il cursore.

Nessun cursore - nessun salto. Ma sui manufatti? L'output ha un numero casuale di righe. Devo riempire tutti gli script con spazi prima di iniziare un nuovo output? Comunque, grazie per il tuo tempo e i tuoi sforzi: +1 da parte mia per questo, ma non risolve il mio problema
Ravnur,

Ho trovato solo un modo per sbarazzarsi di tutti gli artefatti: tput ed. Ma fa battere le palpebre
Ravnur,

Quale emulatore di terminale stai usando? Con tput edsubito prima della do_a_lot...linea, vedo lampeggiare in urxvt ma non xterm o st.

1

Come estensione della risposta di Cristian, ho realizzato la seguente funzione bash che funziona se la finestra della console è più piccola dell'output del comando:

function watcher()
{
    lines=$(tput lines)
    while true; do
        output="$($@ | head -n $lines)"
        clear
        echo -e "$output"
        sleep 2
    done
}

Ciò ti consente di passare qualsiasi comando all'osservatore. Se stai usando git, usa git config --global color.status alwayse poi:

watcher git status

Visualizzerà un output di stato git sempre aggiornato.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.