The trick to this is to call functions which rebinds your keys. In my example I'll use C-b to insert text and to call menu-complete, instead of C-x. You'll have to sacrifice a key, in my example C-t
In .bashrc, or a bash file to be sourced
set_Cb_to_insert_text() {
bind '"C-m": accept-line'
bind '"C-b":"ls C-t1"'
bind -x '"C-t1":set_Cb_to_complete'
}
set_Cb_to_complete() {
bind '"C-m":"C-t2C-t3"'
bind '"C-b": menu-complete'
bind '"C-t2": accept-line'
bind -x '"C-t3":set_Cb_to_insert_text'
}
set_Cb_to_insert_text
How this works:
With bind
, you can bind keys to do one of three things, but no combination of them:
- Execute a readline command:
bind '"key": command'
- Execute a series of keystrokes:
bind '"key":"keystrokes"'
- Execute a shell command:
bind -x '"key": shell-command'
So if you want to combine these three things, you'll need to bind them each to a separate combination of keystrokes (in my example C-t{1,2,3}) and bind a key to execute all these keystrokes.
In the example:
C-b first inserts ls
and 'presses' C-t1, which executes set_Cb_to_complete
, which in turn rebinds C-b to menu-complete
. It also rebinds C-m, carriage return, or Enter, because it now needs to do two things: Accept the line, and reset C-b to insert ls
, by calling the set_Cb_to_insert_text
function, which also resets Enter to it's normal use.
The reason I said that C-t had to be "sacrificed", is that if you press C-t, readline will wait to see if you are going to press 1, or 2, or any of the bound key sequences, before it takes any action. But when you first have put C-t to this use, you can use it as an initial key for a huge amount of keystrokes to cover all your readline trickery.
Piece of advice: While you are writing and testing these, bind an alternate key to accept-line
, because suddenly something breaks the chain at the wrong place, and you are stuck in a terminal without a way to execute commands :)
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…