Cegah teks / layar berkedip saat melakukan clear

11

Skrip saya melakukan sesuatu seperti:

while :;
   clear

   do_a_lot_of_output_here

   sleep 1
done

Apakah ada opsi untuk mencegah layar berkedip saat saya melakukan clear dan output? Saya ingin melakukannya seperti dalam watchperintah (tapi ada tertulis C). Ada saran?

clear | hexdump -C

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

PS. Saya bashhanya menggunakan .

ravnur
sumber
Bisakah Anda menambahkan output Anda clear | hexdump -C?
ott--
Saya telah memperluas pertanyaan.
ravnur
Saya menemukan solusi lain di stackoverflow.com/questions/5367068/… - apakah echo -en "\ec"flash juga?
ott--
Saya menemukan ini juga. Kedua varian dari answer flash juga.
ravnur
Saya sukses dengan alat ini: excess.org/article/2009/07/watch1-bash-unicode
raine

Jawaban:

8

Lampu kilat terjadi karena skrip menghapus seluruh layar. Jika melukis di atas teks yang ada dan membersihkan hanya sesuai kebutuhan, maka tidak akan ada berkedip.

Berikut ini sebuah contoh:

#!/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

Ia melakukan ini:

  • mencetak output dari perintah yang diberikan yang sesuai pada layar (tidak ada pembungkus atau gulir)
  • menulis di atas baris yang ada, membersihkan bagian dari setiap baris yang tidak ditimpa
  • menggunakan edkemampuan terminal Anda untuk mencetak dari lokasi saat ini ke ujung layar.

Jika Anda ingin menangani layar resizable, Anda bisa memindahkan tugas ke ROWSdan COLSdi dalam lingkaran luar, misalnya,

#!/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

karena tputmeminta screensize saat ini dari sistem.

Bacaan lebih lanjut:

Thomas Dickey
sumber
1
Bagi mereka yang menggunakan #!/bin/bashdan ingin menggunakan watchittertanam dalam skrip kecil yang berdiri sendiri dengan beberapa fungsi, Anda dapat melakukannya export -f function_name; watchit function_name.
aggregate1166877
Ini bekerja dengan baik bagi saya kecuali bahwa saya mengalami masalah lucu di bagian atas layar, di mana hal-hal akan berubah dan menjadi glitchy untuk potongan teks yang lebih lama (apa pun yang dipersingkat head). Tampaknya masalah ini adalah kesalahan satu per satu (setidaknya dalam pengaturan saya - sesi ssh di panel split, iTerm2) ketika menghitung jumlah baris. ROWS=`expr $(tput lines) - 1`mengatasinya dengan sempurna.
ohruunuruus
Ini luar biasa, terima kasih banyak @ thomas-dickey.
mbarkhau
9

Salah satu cara untuk membantu mencegah flashing adalah dengan mendapatkan semua output sebelum membersihkan layar sehingga ada waktu minimum antara membersihkan dan menggambar ulang itu. Ini mirip dengan konsep buffering ganda:

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

Ini tidak sepenuhnya menghilangkan flicker, tetapi itu terjadi secara signifikan lebih jarang dalam pengalaman saya.

Cristián Romo
sumber
Penyangga ganda, sama seperti dalam situasi lain, brankas hari ini :-)
Ikke
Bekerja seperti pesona. Tidak berkedip sama sekali :)
Lars Juel Jensen
1
Kelap-kelip yang tersisa dapat dihilangkan dengan memasukkan clearke dalam buffer, yaitu output=$(clear; do_a_lot_of_output_here).
kdb
@ kdb Saran yang bagus! Ini hampir sepenuhnya menghilangkan kedipan bagi saya dan jauh lebih sederhana daripada jawaban yang diterima.
Michael Mior
Ini bekerja seperti pesona! Pada awalnya saya melewatkan tanda kutip ganda di 'echo "$ output"', dan kemudian garis menjadi kacau. (Semua spasi putih dianggap sebagai ruang tunggal.)
Popup
5

Lampu kilat adalah hasil yang tidak terhindarkan dari membersihkan layar setiap kali di sekitar loop. Anda dapat memindahkan kursor ke bagian atas layar dan menimpa bagian dari output lama Anda sebagai gantinya.

# 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

Script ini akan meninggalkan artefak jika output Anda menyusut. Ini juga tidak terlalu portabel. Saya hanya mengujinya dengan urxvt, xterm, dan st.


sumber
Dalam hal ini kursor mulai melompat ke akhir output dari posisi acak (dan tentu saja artefak). Saya juga mencoba tput cleardengan hasil yang sama (berkedip)
ravnur
Saya menambahkan beberapa baris ke skrip untuk menyembunyikan kursor.
Tanpa kursor - tidak ada lompatan. Tetapi tentang artefak? Output memiliki jumlah baris acak. Apakah saya perlu mengisi semua skrip dengan spasi sebelum memulai output baru? Tapi, bagaimanapun, terima kasih atas waktu dan upaya Anda: +1 dari saya untuk itu tetapi itu tidak menyelesaikan masalah saya
ravnur
Saya hanya menemukan satu cara untuk menyingkirkan semua artefak: tput ed. Tapi itu menyebabkan berkedip
ravnur
Emulator terminal apa yang Anda gunakan? Dengan tput edtepat sebelum do_a_lot...baris, saya melihat berkedip di urxvt tetapi tidak xterm atau st.
1

Sebagai perpanjangan dari jawaban Cristian, saya membuat fungsi bash berikut yang berfungsi jika jendela konsol lebih kecil dari output perintah:

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

Ini memungkinkan Anda untuk memberikan perintah apa pun kepada pengamat. Jika Anda menggunakan git, gunakan git config --global color.status alwaysdan kemudian:

watcher git status

Akan menampilkan keluaran status git yang selalu diperbarui.

eresonance
sumber