PS1 meminta untuk menampilkan waktu yang telah berlalu

10

Saat ini saya menggunakan ini untuk menampilkan waktu saat ini di bash prompt saya:

PS1=\[\e[0;32m\]\t \W>\[\e[1;37m\]

20:42:23 ~>

Apakah mungkin untuk menampilkan waktu yang telah berlalu sejak prompt sebelumnya? Seperti:

00:00:00 ~> sleep 10
00:00:10 ~> sleep 20
00:00:20 ~>

Ini tidak memiliki kesamaan dengan Apakah mungkin untuk mengubah PS1 secara berkala dengan skrip di latar belakang?

TeasingDart
sumber
Tidak, tidak ada jawaban dalam posting itu dan saya berharap prompt berubah hanya ketika prompt baru ditampilkan.
TeasingDart
Sebenarnya tidak ada cara yang layak untuk melakukan apa yang Anda minta, tidak.
DopeGhoti
1
Ini layak jika nilai yang ditampilkan adalah statis (pertanyaan OP tampaknya tidak memungkinkan untuk itu). Waktu yang berlalu dapat dipertahankan dengan menyimpan waktu zaman sebelumnya dalam variabel shell. Menerapkannya sepertinya banyak pekerjaan (sekitar satu jam atau lebih - mungkin seseorang akan memberikan solusi yang lebih sederhana daripada yang ada dalam pikiran saya). Pertanyaan ini akan sangat membantu.
Thomas Dickey

Jawaban:

10

Salah satu cara untuk melakukannya adalah dengan menggunakan fitur PROMPT_COMMAND dari bash untuk mengeksekusi kode yang memodifikasi PS1. Fungsi di bawah ini adalah versi terbaru dari kiriman asli saya; yang satu ini menggunakan dua variabel lingkungan yang lebih sedikit dan mengawali mereka dengan "_PS1_" untuk mencoba menghindari variabel variabel yang ada.

prompt_command() {
  _PS1_now=$(date +%s)
  PS1=$( printf "\[\e[0;32m\]%02d:%02d:%02d \W>\[\e[1;37m\] " \
           $((  ( _PS1_now - _PS1_lastcmd ) / 3600))         \
           $(( (( _PS1_now - _PS1_lastcmd ) % 3600) / 60 )) \
           $((  ( _PS1_now - _PS1_lastcmd ) % 60))           \
       )
  _PS1_lastcmd=$_PS1_now
}
PROMPT_COMMAND='prompt_command'
_PS1_lastcmd=$(date +%s)

Masukkan itu ke dalam .bash_profile Anda untuk memulai sesuatu.

Perhatikan bahwa Anda harus mengetik dengan cukup cepat untuk mendapatkan sleepparameter yang cocok dengan parameter prompt - waktu sebenarnya adalah perbedaan antara konfirmasi, termasuk waktu yang diperlukan untuk mengetik perintah.

00:00:02 ~> sleep 5   ## here I typed really quickly
00:00:05 ~> sleep 3   ## here I took about 2 seconds to enter the command
00:00:10 ~> sleep 30 ## more slow typing
00:01:35 ~>

Tambahan terlambat:

Berdasarkan jawaban yang sekarang dihapus oleh @Cyrus, berikut adalah versi yang tidak mengacaukan lingkungan dengan variabel tambahan:

PROMPT_COMMAND='
    _prompt(){
        PROMPT_COMMAND="${PROMPT_COMMAND%-*}-$SECONDS))\""
        printf -v PS1 "\[\e[0;32m\]%02d:%02d:%02d \W>\[\e[1;37m\] " \
                      "$(($1/3600))" "$((($1%3600)/60))" "$(($1%60))"
    }; _prompt "$((SECONDS'"-$SECONDS))\""

Tambahan keterlambatan ekstra:

Mulai di bash versi 4.2 ( echo $BASH_VERSION), Anda dapat menghindari datepanggilan eksternal dengan string format printf baru; ganti $(date +%s)potongan dengan $(printf '%(%s)T' -1). Mulai dalam versi 4.3 , Anda dapat menghilangkan -1parameter untuk mengandalkan perilaku "tidak ada argumen berarti sekarang ".

Jeff Schaller
sumber
Ini sangat dekat. Ini berfungsi ketika saya menyalin / menempel dari bash prompt, tetapi ketika saya mencoba menambahkannya ke .bashrc saya mencetak "1451424431: perintah tidak ditemukan"
TeasingDart
mungkin sedikit terlalu banyak menyalin / menempel?
Jeff Schaller
Versi terakhir ini berfungsi, persis seperti yang saya inginkan! Saya pikir itu ada hubungannya dengan jebakan saya untuk mengatur warna teks setelah prompt. Terima kasih.
TeasingDart
ketika Anda meresetnya $SECONDSberhenti untuk melacak waktu sejak shell dimulai,
mikeserv
1
@ chepner - well, tentu, tapi itu tidak menjaga waktu shell lagi. jangan salah paham - saya membatalkannya karena ini adalah jawaban yang bagus - tetapi saya pikir mendefinisikan ulang shell interaktif $SECONDSuntuk setiap prompt cenderung menimbulkan perilaku tak terduga. fungsi shell lain yang mungkin menggunakannya untuk alasan apa pun yang terkait dengan evaluasi run-time akan berperilaku salah.
mikeserv
4
PS1[3]=$SECONDS
PS1='${PS1[!(PS1[1]=!1&(PS1[3]=(PS1[2]=$SECONDS-${PS1[3]})/3600))
   ]#${PS1[3]%%*??}0}$((PS1[3]=(PS1[2]/60%60),  ${PS1[3]})):${PS1[1
   ]#${PS1[3]%%*??}0}$((PS1[3]=(PS1[2]%60),     ${PS1[3]})):${PS1[1
   ]#${PS1[3]%%*??}0}$((PS1[3]=(SECONDS),       ${PS1[3]})):'$PS1

Ini menangani pemformatan dengan kalkulasi - jadi, meskipun ia berkembang beberapa kali, ia tidak melakukan subshell atau pipa.

Itu hanya memperlakukan $PS1sebagai array dan menggunakan indeks yang lebih tinggi untuk menyimpan / menghitung setiap / semua keadaan yang diperlukan antara prompt. Tidak ada kondisi shell lain yang terpengaruh.

00:00:46:[mikeserv@desktop tmp]$
00:00:01:[mikeserv@desktop tmp]$
00:00:00:[mikeserv@desktop tmp]$
00:00:01:[mikeserv@desktop tmp]$
00:00:43:[mikeserv@desktop tmp]$ sleep 10
00:00:33:[mikeserv@desktop tmp]$ sleep 10
00:00:15:[mikeserv@desktop tmp]$
00:00:15:[mikeserv@desktop tmp]$
00:00:02:[mikeserv@desktop tmp]$
00:02:27:[mikeserv@desktop tmp]$

Saya bisa memecahnya sedikit mungkin ...

Pertama, simpan nilai saat ini dari $SECONDS:

PS1[3]=$SECONDS

Selanjutnya, definisikan $PS1[0]untuk menjadi self-recursive dengan cara yang akan selalu menetapkan nilai yang tepat untuk $PS1[1-3]sekaligus referensi diri. Untuk mendapatkan bagian ini Anda harus mempertimbangkan urutan ekspresi shell-matematika dievaluasi. Yang paling penting, shell-matematika selalu urutan terakhir dari bisnis untuk shell-matematika. Sebelum semua yang lain, shell memperluas nilai. Dengan cara ini Anda bisa mereferensikan nilai-lama untuk variabel-shell dalam ekspresi matematika setelah menetapkan dengan menggunakan $.

Berikut ini contoh sederhana:

x=10; echo "$(((x+=5)+$x+x))" "$x"

40 15

Shell akan mengevaluasi pernyataan itu dengan terlebih dahulu mensubstitusi nilai di $xmana pun $referensi tanda dolar digunakan, dan dengan demikian ungkapan menjadi:

(x+=5)+10+x

... lalu shell menambahkan 5 ke nilai $xdan kemudian memperluas seluruh ekspresi menjadi x+10+x, sementara hanya mempertahankan nilai yang sebenarnya ditugaskan dalam variabel referensi. Dan nilai diperluas ekspresi matematika adalah 40, tetapi nilai akhir $xadalah 15.

Itulah sebagian besar cara kerja $PS1persamaan juga, kecuali bahwa ada tingkat lebih lanjut dari ekspansi / evaluasi matematika yang dieksploitasi dalam indeks array.

PS1='${PS1[!(PS1[1]=!1&(...))]#...}...'

Saya tidak benar-benar yakin mengapa saya memilih untuk menggunakan di PS1[1]=!1sana - saya kira itu mungkin hanya estetika konyol - tetapi ini memberikan 0 $PS1[1]saat memperluas itu untuk substitusi parameter. Nilai bitwise AND untuk 0 dan yang lainnya akan selalu 0, tetapi tidak mengalami hubung pendek seperti yang &&dilakukan boolean saat yang paling utama adalah 0 sehingga ekspresi kurung masih dievaluasi setiap waktu. Itu penting, tentu saja, karena elipsis pertama adalah tempat nilai awal $PS1[2,3]ditetapkan.

Pokoknya, di $PS1[1]sini dijamin 0 bahkan jika itu dirusak antara penarikan cepat. Di dalam kurung ada ...

PS1[3]=(PS1[2]=$SECONDS-${PS1[3]})/3600

... $PS1[2]ditugaskan perbedaan $PS1[3]dan $SECONDS, dan $PS1[3]diberi hasil bagi dari nilai itu dan 3600. Semua nilai di sini diinisialisasi. Dan sebagainya:

${PS1[1]#${PS1[3]%%*??}0}

... jika ada setidaknya dua digit di dalam $PS1[3]maka ekspansi batin ada nol, dan karena kita tahu $PS1[1]0 maka jika $PS1[3]bisa diganti dengan tidak ada, begitu juga apakah $PS1[1]itu diperluas ke nilainya. Dengan cara ini hanya nilai satu digit untuk setiap iterasi $PS1[3]penugasan akan memperluas nol di depan, dan $PS1[3]itu sendiri diperluas modulo 60 segera setelah itu sementara secara bersamaan diberi nilai berikutnya yang lebih kecil berturut-turut untuk setiap jam, menit, detik.

Bilas dan ulangi, hingga iterasi terakhir saat $PS1[3]ditimpa dengan nilai saat ini $SECONDSsehingga dapat dibandingkan dengan $SECONDSsekali lagi saat prompt diambil berikutnya.

mikeserv
sumber
1

Solusi terbaik yang saya temukan sejauh ini adalah ini: https://github.com/jichu4n/bash-command-timer

Yang mencetak [ 1s011 | May 25 15:33:44 BST ]alias waktu yang telah berlalu di sisi kanan setelah perintah dieksekusi, sehingga tidak mengacaukan Anda PS1.

Seluruh string dan format waktu dapat dikonfigurasi. Bahkan warna dan ketepatan dapat dikonfigurasi. Saya tahu itu mungkin agak banyak untuk minimalis di luar sana, tapi itu keren.

sebs
sumber