14

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

2 Answers 2

20

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-t2\C-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 :)

Sign up to request clarification or add additional context in comments.

1 Comment

thank you so much for the idea, example and detailed answer (convoluted, yes, but you worked within the the bash+readline framework and their limitations). Over a year after my post I can only remember vaguely what I was trying to do in the big picture ... so I just verified that your example works but will invest more time recreating what I was trying to previously accomplish - Thanks!
4

This might work for you:

"\ex": menu-complete
"\ez": "ls \ex"

Include these lines in your ~/.inputrc file.

These lines set Alt-x to menu-complete and Alt-z to ls space menu-complete. This will give you the first file in the directory and use Alt-x to cycle through the remainder one at a time.

See here for more examples of macros.

Checkout the readline commands by invoking bind -p or bind -P and bind -s will show the macros you already have. See here for the bind command also you can make one off macros too, see here. Lastly check that the .inputrc file is being read, I had trouble because the environmental variable was set to /etc/Inputrc and my personal version was never being invoked.

BTW steer clear of Control-x as it is already in use for many readline commands.

4 Comments

This almost does the trick but requires 2 key combos for the subsequent calls. I already had the knowledge of how to bind text insertion and how to bind menu-complete... If I "Alt-z" a second time I would want the display just to show ls <secondfile>, but instead I see ls <firstfile> ls<secondfile> ...
This would imply (and I may be wrong here), that you want the same key combination to toggle it's action. On reading the documentation of the readline library the only conditional precepts are concerned with mode i.e. bash, emacs, ftp... Perhaps in this case you may need to write a new readline function see here. BTW Look at this way ... Alt-x and Alt-z are not a million miles apart (well not on my keyboard) and a key combination for menu-complete comes in handy in general.
Actually, on my mac, the keycombos you mention are only responding to Esc-x, Esc-z, and at that the trailing "\ex" doesn't seem to actually do anything
Sorry I don't have a Mac so I don't know the characters to use for one. But a thought just struck me, if you're an emacs user, keyboard macros are recordable too and you can name them and recall them via the .init file. Perhaps using the M-x shell or M-x terminal is your best bet - good luck.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.