6

I can only find examples of setting Readline key bindings using Control (\C-) or Escape (\e) as prefixes.

In my case, on macOS, the \C- space is completely filled up by default key bindings, and the \e space is not practical on a Macbook with a touchbar.

Entering "\M-f": kill-word in ~/.inputrc results in:

bind -P | grep -F "\M-"
kill-word can be found on "\e[3;5~" "\ed".

But kill-word cannot be executed using either of Option, Command, or fn as prefixes - Readline ignores it.

Is this issue specific to macOS, and how can I solve it?

Furthermore, how can I control the "timeout" that should occur before a key binding, that is a prefix of a longer key binding, is executed?

@added (@laktak): bind '"^[f": kill-word' doesn't work, but instead results in ƒ on the terminal: enter image description here

19
  • Does using something other than f work? Since (at least on my Linux) \M-f is already bound to forward-word, perhaps that's causing a conflict.
    – terdon
    Commented Sep 8, 2019 at 11:35
  • Not in my case, bind -q forward-word results in forward-word can be invoked via "\e[1;3C", "\e[1;5C", "\ef".
    – Shuzheng
    Commented Sep 8, 2019 at 11:38
  • Do you know if Readline only allows \e and \C as special prefixes?
    – Shuzheng
    Commented Sep 8, 2019 at 11:39
  • Well yes, \ef is M-f. Does it work if you use another letter?
    – terdon
    Commented Sep 8, 2019 at 11:42
  • 1
    Your terminal emulator should send an Escape, f to the program inside the terminal when you press Option + F or whatever. Or it can be configured to do that.
    – user313992
    Commented Sep 8, 2019 at 13:10

4 Answers 4

7

I don't think you're doing anything wrong, you just need to tell Terminal.app to use the "Option" key as "Meta" instead. Just go to the preferences for Terminal (+,), then Profiles, then the Keyboard tab for your default profile and check "Use Option as Meta key."

Screenshot of Terminal.app "Profiles" → "Keyboard" settings

Otherwise, you're getting the default macOS behavior (in most keymaps) where Option + key produces special characters, just like Option+f yields the small letter "f" with hook from your screenshot (complete reference here).

In iTerm 2, I believe the left Option key already does the sensible thing by default, but just in case, here's how to change that:

iTerm 2 Option key behavior

As far as remapping Option to Escape, if that's a thing you still wanted to do, that can be accomplished from the Keyboard prefpane in System Preferences, by clicking the "Modifier Keys…" button near the bottom of the window.

macOS System Settings Keyboard prefpane

Then remap it to whatever you please (from the available choices):

Remapping modifier keys in the macOS Keyboard prefpane

I hit up this preference pane in about the first five minutes of using a new Mac, just so I can remap Caps Lock to Control, since the Control key on a Mac keyboard is in an awkward spot.

1
  • I should add that the option key in macOS is faaaaar too useful to be remapping to something else. As an experiment, switch to Finder and open any menu (even the Ctrl+click / right-click context menu) and watch what happens when you press and release the "Option" key.
    – Kevin E
    Commented May 31, 2020 at 13:42
2

The utility would be:

showkey (1)          - examine the codes sent by the keyboard

but this seems to be missing on mac-os...here it is "Key Codes"...?

Or you type ctrl-V (qouted insert) and then some special key. In bash, this prints ^[OP in xterm and ^[[[A in the console for the F1 key.

The readline variable:

keyseq-timeout (500)

is the timeout to use for a half-finished sequence.

Underneath this, there must be a sort of keymap file, where the keys get translated to symbols. This is from /usr/share/kbd/keymaps/mac/ on linux:

keycode 51 = Delete  Remove
        alt keycode 51 = Meta_Delete
        shift alt keycode 51 = Meta_Delete
        control keycode  51 = Remove
keycode 53 = Escape
        alt keycode 53 = Meta_Escape
        shift alt keycode 53 = Meta_Escape
keycode  54 = Control
keycode  55 = Alt         # Command/Apple key
keycode  56 = Shift
keycode  57 = Caps_Lock
keycode  58 = AltGr       # Alt/Option key

You see the flexibilty! The Meta-Delete symbol could become kill-word...


bind '"^[f": kill-word

This ^[ must be a \e, or a ctrl-V, then Escape: one byte, not circumflex plus bracket.


It is like saying: ^C means control-C, not a Shift-6 and then a Shift-c...in the shell (bash) or in vim when I type ctrl-v and then Esc I get ^[, but it is just one character when you step back over it. Together with these meta-flag options in readline it can get complicated...I just illustrate the whole chain:

keymap "default.map" (translates scancode and modifier to keysymbols)

keycode 105 = Left F150 F151
  string F150 = "\033[150"
  string F151 = "\033[151"
keycode 106 = Right F154 F155
  string F154 = "\033[154"
  string F155 = "\033[155"

The F150 and F151 after default "Left" mean shift- and control-left-arrow. In a second step you can define a string, an escape sequence in this case. Here, \e did not work, but the octal 033 is ascii 27 is control-[ is Escape...this keymap is linux specific, but X Windows has a similar logic.

And in .inputrc:

"\e[150": backward-word 
"\e[151": shell-backward-word 
"\e[154": forward-word 
"\e[155": shell-forward-word 

This works very nice in the linux console. In xterm under X Windows (Xorg): not at all: Xorg scans the keys itself.

backward-word can be invoked via "\e[150", "\e[1;2D", "\e[1;3D", "\eb".

The two in the middle with semicolon are VTxxx style modified left arrows. This was preconfigured, and also gets bound to backward-word automatically.

6
  • Thanks is keyseq-timeout in milliseconds? Do you see it in man bash, or where should I look? You're right, showkey is not available on macOS through brew. I cannot get you Ctrl-V trick to work in iTerm :(
    – Shuzheng
    Commented Sep 8, 2019 at 18:24
  • What do you mean by "console"? Isn't xterm the same as the console?
    – Shuzheng
    Commented Sep 8, 2019 at 18:26
  • I'm not sure what you mean by "This ^[ must be a \e, or a ctrl-V, then Escape: one byte, not circumflex plus bracket."? Could I use ^[ instead of \e?
    – Shuzheng
    Commented Sep 8, 2019 at 18:34
  • xterm is a (VT220) terminal emulator in a GUI. The linux console is the built-in virtual tty. The example (F1 key) in my answer shows one difference. xterm uses XKB from X Windows for key mapping, modifiers, kbd layout. I see now I have kill-word on \e[3;5~ like you --- this is Control-Delete for X. On the console the Delete and arrow keys did not have any Shift- or Control mofifiers defined.
    – user370539
    Commented Sep 8, 2019 at 20:03
  • thanks. Off-topic: how do I identify whether I'm talking to the Linux console built-in virtual tty, or some other terminal emulator?
    – Shuzheng
    Commented Sep 9, 2019 at 5:10
0

If I understood your question correctly:

bind '"^[f": kill-word'

Will define Option+F to invoke kill-word

3
  • Thanks, @laktak. How do I see that ^[f means Option? Are there also symbols for e.g. Command? Also, do you know the answer to, how to control the "timeout" before Readline uses a key binding that's a prefix of another key binding?
    – Shuzheng
    Commented Sep 8, 2019 at 13:04
  • your solution doesn't seem to work. Option+f results in ƒ in the terminal.
    – Shuzheng
    Commented Sep 8, 2019 at 13:15
  • @Shuzheng press Control+v (at the prompt) and then type the key combination you want to use - this should show you the keycode for the bind.
    – laktak
    Commented Sep 8, 2019 at 14:57
0

The other option is to use Esc and then hit the d button, with that you can simulate the same keybinding.

Same as pasting the last argument of the previous command (M-.) could be replaced by hitting Esc first and then ..

To help myself on my MacBooks starting with the Touch Bar versions I've remapped the Caps Lock ⇪ with ⎋ Escape

Remapping Caps Lock

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .