Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
258 views
in Technique[技术] by (71.8m points)

readline - Complex keybinding in bash

Is there a way to combine two operations into one keybinding (dont think would work with function).

This is what I'd like to do:

I'd like a keybinding (say Ctrl-X) to -

  1. insert some text, then
  2. invoke the complete or menu-complete, using the inserted text as the basis for the completion

I know that I can (in ~/.inputrc) specify

  • Insertion of text with (C-X: "ls")
  • Execute readline commands (C-SPACE: menu-complete)

But I am not sure how to put these together

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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 :)


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...