Menampilkan stdout dari proses latar belakang di lokasi spesifik terminal

8

Saya memiliki perintah yang saya jalankan setiap kali terminal baru dibuka atau login baru dibuat.

Program ini menghasilkan output (berwarna) yang harus diposisikan sebelum command prompt. Butuh beberapa detik untuk menjalankan yang akan mencegah saya menggunakan terminal sampai saat itu (kecuali berlari di latar belakang).

Mengingat bahwa zsh memiliki beberapa cara canggih untuk menggambar ulang terminal tanpa mengalahkan teks yang ada, saya ingin tahu bagaimana saya bisa menjalankan perintah ini dengan cara yang saya tidak harus menunggu sampai selesai sebelum saya dapat menggunakan terminal tapi itu setelah selesai mencetak hasil cetak seolah-olah tidak di latar belakang di tempat pertama.

Dalam praktiknya saya ingin sesuatu yang bisa dilakukan:

Command output:
... (running on background)
me@computer: somecommand
me@computer: someothercommand

dan setelah perintah selesai saya akan mendapatkan:

Command output:
 * Output foo
 * Multiple lines bar
 * and some yada
me@computer: somecommand
me@computer: someothercommand

Saya mencoba meletakkan proses di latar belakang saat mulai tetapi kemudian tidak menampilkan output dengan bersih. Saya mendapatkan sesuatu seperti:

Command output:
[2] 32207
me@computer: somecommand
me@computer: someother * Output foo
 * Multiple lines bar
 * and some yada
[2]  + done       command
me@computer: someothercommand

Jadi, apakah ini mungkin? Jika tidak dengan zsh apakah ada solusi di luar sana yang bisa melakukannya?

Setiap petunjuk atau informasi diterima.

unode
sumber
Tidak mungkin jika program berjalan langsung di terminal, karena hanya ada satu posisi kursor dan zsh dan program akan bersaing untuk itu. Anda dapat melakukan sesuatu dengan zpty: minta perintah dijalankan di terminal yang dibuat oleh zsh, dengan outputnya diteruskan ke terminal nyata di bawah kendali zsh.
Gilles 'SANGAT berhenti menjadi jahat'
@Gilles Bisakah Anda menguraikan penggunaan zpty? Saya menyadari bahwa Anda tidak dapat memiliki dua program menulis ke terminal yang sama tanpa semacam persaingan atas kursor. Pertanyaan saya berasal dari fakta bahwa zsh sudah menulis ulang prompt dalam beberapa konfigurasi. Jelas program ini harus menulis ke beberapa buffer dalam memori sementara yang kemudian akan "dicetak" ke lokasi tertentu setelah perintah selesai. Semua yang terakhir di bawah kendali zsh.
unode
@Gilles: mungkin ini layak jawaban nyata?
Stéphane Gimenez
@ StéphaneGimenez Tentu, benar. Saya tidak tahu bagaimana melakukannya tanpa riset, dan saya tidak punya waktu untuk riset ini sekarang.
Gilles 'SANGAT berhenti menjadi jahat'
Gagasannya adalah melakukan ini dengan screenskrip startup yang membagi layar dan menjalankan runner panjang di bagian atas dan baris perintah normal di bagian bawah.
vasquez

Jawaban:

5

Ini adalah solusi sederhana jika Anda bersedia menerima output tepat di atas garis prompt saat ini.

TRAPUSR1 () { zle -I; unfunction TRAPUSR1 }  # invalidate prompt on signal USR1

bufferout () {
    local buffer
    while read -r line; do                   # buffer lines from stdin
        buffer="$buffer$line\n"
    done
    print -rn -- $terminfo[dl1]              # delete current line
    print -rn -- $terminfo[cr]               # move cursor to BOL
    printf "$buffer"                         # print buffer
    kill -USR1 $$                            # send USR1 when we're done
}

unsetopt monitor                             # don't monitor this job
./testout |& bufferout & disown              # bg and disown to suppress notification
setopt monitor                               # restore job monitoring

Ketika pekerjaan selesai, prompt saat ini dan input buffer akan dihapus dan keseluruhan dari perintah stdoutdan stderrakan dicetak.

Anda bisa mendapatkan jauh lebih mewah dari itu dengan zsh/cursesmodul, tapi saya ragu itu akan menawarkan keuntungan yang cukup signifikan untuk pantas dilakukan.

user112553
sumber
Ini bekerja. Tetapi seberapa sulitkah untuk mencegah shell dari mencetak proses pid ketika dikirim ke latar belakang dan pesan "selesai" setelah selesai? (Maksud saya untuk sementara menonaktifkan fitur itu). Juga, sebelum meletakkan output pada terminal, seberapa sulitkah untuk menghapus garis atau garis prompt yang ada?
unode
Saya pikir saya mungkin memiliki beberapa konfigurasi penulisan ulang prompt yang bertabrakan dengan penghapusan prompt awal. Milik saya tidak pergi begitu perintah selesai. Saya juga masih mendapatkan PID dari proses ketika dikirim ke latar belakang tetapi baris "selesai" hilang. Bagaimanapun saya menerima jawaban Anda karena cukup dekat dengan apa yang ada dalam pikiran saya. Terima kasih.
unode
Saya menggunakan xterm dan saya memiliki modul VCS diaktifkan dan beberapa penyesuaian lainnya ke prompt. Saya belum mencoba tetapi saya cukup yakin itu ada hubungannya dengan itu. Beberapa waktu lalu saya mencoba menggunakan notifier mode vi mirip dengan yang ini ( stackoverflow.com/a/3791786/125801 ) dan ketika aktif saya kehilangan beberapa perilaku prompt kustom saya. Ini bukan masalah besar, saat ini saya senang dengan solusinya. Saya akan mencoba untuk membersihkan prompt saya suatu hari ini dan memeriksa apakah PID masih muncul.
unode
Zsh-4.3.10, setelah menonaktifkan hampir setiap kustomisasi, saya sekarang tidak lagi mendapatkan prompt (yaitu sudah dihapus dengan benar) tapi saya masih mendapatkan PID dari proses di latar belakang, seperti [1] 27911 27912dalam satu baris dan sebagai baris pertama pada terminal.
hapus kode
Bisakah saya memilih lagi? :) Sempurna sekarang! Terima kasih banyak.
hapus kode