Pintasan keyboard riwayat Bash untuk! *

8

Di Bash, ada beberapa operator praktis untuk mengulangi bagian dari perintah terakhir:

  • !^ memperluas argumen pertama dari perintah sebelumnya, misalnya,

    $ echo one "two three"
    one two three
    $ echo !^
    echo one
    one
  • !$ memperluas argumen terakhir dari perintah sebelumnya, misalnya,

    $ echo one "two three"
    one two three
    $ echo !$
    echo "two three"
    two three
  • !* memperluas ke semua argumen dari perintah sebelumnya, misalnya,

    $ echo one "two three"
    one two three
    $ echo !*
    echo one "two three"
    one two three

(Sejauh yang saya mengerti, ini adalah gula sintaksis untuk !!:^, !!:$dan !!:*masing - masing, di mana !!penunjuk acara yang memperluas perintah sebelumnya, dan ^, $dan *penentu kata, lihat Manual Referensi Bash atau man bash.)

Ini seringkali cukup berguna. Tetapi semakin keren dengan pintasan keyboard:

  • Ketika Anda menekan Alt+ .atau Alt+ _, argumen terakhir dari perintah sebelumnya dimasukkan dalam perintah saat ini, sama seperti jika Anda telah menulis !$pada titik itu.

  • Dimungkinkan juga untuk menekan Alt+ Ctrl+ yuntuk memasukkan argumen pertama dari perintah sebelumnya, seolah-olah Anda telah menulis !^pada titik itu.

(Lihat Perpustakaan Readline GNU atau info readline.)

Saya cenderung lebih suka pintasan keyboard daripada operator sejarah Bash, karena saya bisa melihat apa yang saya masukkan sebelum saya benar-benar menjalankan perintah. Namun, sepertinya tidak ada jalan pintas yang memungkinkan saya untuk memasukkan semua kata dari perintah sebelumnya, yaitu kata yang !*berfungsi. Setidaknya saya tidak dapat menemukannya.

Apakah ada jalan pintas seperti itu? Jika tidak, apakah mungkin untuk mengonfigurasi perpustakaan readline untuk menambahkannya, dan bagaimana caranya?

Malte Skoruppa
sumber
AFAIK, pintasan keyboard ditangani oleh emulator terminal. Jadi saya kira Anda menggunakan terminal gnome?
Seth
1
Di zsh, jika Anda mengetik echo !*dan kemudian menekan TAB, Anda memiliki efek yang diinginkan. Secara umum, TAB sambil membaca akan memperluas semua yang dapat diperluas. Sangat berguna; mungkin bash akan memiliki beberapa konfigurasi dengan efek yang sama? @Seth, saya pikir ini adalah readline ke bash, bukan terminal emulator - meskipun tidak yakin.
Rmano
2
@Seth Tidak, pintasan dari Q ditangani oleh bash. Anda dapat melakukan serch untuk 'Perintah untuk Memanipulasi Sejarah' di man bash( di suatu tempat di garis 3030)
Radu Rădeanu
@ RaduRădeanu Oh menarik! Saya tidak tahu itu. Buruk untuk asumsi buruk.
Seth
1
\e.dan \e_dipetakan ke fungsi readline yank-last-argdan \e\C-ydipetakan ke yank-nth-arg. Sayangnya sepertinya tidak ada perintah (tunggal) yang menambahkan beberapa argumen sebelumnya sekaligus.
Adaephon

Jawaban:

5

Jika Anda melihat output dari perintah berikut:

bind -l

atau lebih baik untuk:

bind -l | grep arg

Anda dapat melihat bahwa tidak ada fungsi readline untuk semua argumen seperti, misalnya, yank-last-arguntuk argumen terakhir - yang dapat menyisipkan argumen terakhir ke perintah sebelumnya (kata terakhir dari entri riwayat sebelumnya). Jadi, jika fungsi seperti itu tidak ada, kemungkinan besar tidak ada jalan pintas untuk mencapai apa yang Anda inginkan.

Mari kita coba membuat satu yang mendekati permintaan Anda ...

Pertama, lihat misalnya pada output dari perintah berikut:

bind -p | grep yank-nth-arg

Outputnya adalah:

"\e\C-y": yank-nth-arg

dan dapat diterjemahkan sebagai berikut: yank-nth-arg(yang menyisipkan argumen pertama ke perintah sebelumnya - dengan argumen n, masukkan argumen ke-n dari perintah sebelumnya) terikat ke Alt+ Ctrl+ y.

Dengan cara yang sama dapat diartikan setiap baris dari output bind -pperintah.

Sekarang, perhatikan skenario berikut:

  • Jika Anda mengatur ikatan berikut:

    bind '"\ea": "\e2\e."'

    Alt+ Aakan dipetakan ke Alt+ 2Alt+ .yang dipetakan untuk memasukkan argumen kedua dari perintah sebelumnya. Jadi, setelah ketika Anda menekan Alt+ A, argumen kedua dari perintah sebelumnya dimasukkan dalam perintah saat ini.

  • Jika Anda mengatur:

    bind '"\ea": "\e1\e. \e2\e."'

    Setelah ketika Anda menekan Alt+ A, dua argumen pertama dari perintah sebelumnya dimasukkan dalam perintah saat ini. Jika jumlah argumen dari perintah sebelumnya maksimum 2, tentu saja semua perintah sebelumnya dimasukkan dalam perintah saat ini.

  • Jika Anda mengatur:

    bind '"\ea": "\e1\e. \e2\e. \e3\e."'

    Setelah ketika Anda menekan Alt+ A, tiga argumen pertama dari perintah sebelumnya dimasukkan dalam perintah saat ini. Jika jumlah argumen dari perintah sebelumnya maksimum 3 (seperti dalam kasus Anda), tentu saja semua perintah sebelumnya dimasukkan dalam perintah saat ini.

  • Dan seterusnya.

Untuk 10 argumen pertama, Anda dapat menggunakan:

bind '"\ea": "\e1\e. \e2\e. \e3\e. \e4\e. \e5\e. \e6\e. \e7\e. \e8\e. \e9\e. \e1\e0\e."'

Dan saya pikir ini cukup lama sejauh saya tidak menggunakan perintah terlalu sering dengan banyak argumen.

Untuk membuatnya gigih, tambahkan baris berikut ke ~/.inputrcfile Anda :

"\ea": "\e1\e. \e2\e. \e3\e. \e4\e. \e5\e. \e6\e. \e7\e. \e8\e. \e9\e. \e1\e0\e."

Dalam contoh ini saya memilih Alt+ Auntuk menyisipkan semua argumen (jika jumlah argumen tidak lebih dari 10) dari perintah sebelumnya, tetapi Anda dapat memilih kombinasi lain dengan mengganti perintah sebelumnya, \eastring.

Sumber:

Radu Rădeanu
sumber
Yah, ini agak meretas, dan itu hanya akan bekerja untuk sejumlah argumen, tetapi tampaknya yang paling dekat kita dapat dengan mudah - saya akan menerimanya;) Sebenarnya saya hanya melihat pada kode sumber readline. Sekilas seperti dalam file funmap.c, fungsi yank-nth-argdipetakan ke fungsi C rl_yank_nth_arg, yang pada gilirannya didefinisikan dalam kill.c. Secara analog untuk yank-last-arg. Tentu saja mungkin untuk memperluas readline dengan fungsi seperti itu, tetapi saya tidak ingin melakukan itu; Saya lebih suka readline saya dikelola apt, dan fitur ini tidak begitu penting;)
Malte Skoruppa