Run external command in inputrc mapping, without modifying current line

bashtmuxzsh

I have mapped C-h, C-j, C-k, C-m key combinations in tmux.conf to switch between panes, but really miss the C-h combination for backspace when using bash / zsh.

I have enabled vi mode in ~/.inputrc and was thinking of mapping C-h to backward-delete-char in vi-insert mode, and to run tmux select-pane -L in vi-command mode.

How can I add a mapping in vi-command mode to run the command tmux select-pane -L in background, without modifying the current line and its cursor position?

Best Answer

Bash

This is possible, but not through inputrc. (This file belongs to the Readline library, which – although mostly known from Bash – is actually a generic text input library used by many different programs and doesn't really deal with shell-specific things like "running a command".)

Instead, this is a custom action provided by Bash itself (not available in other Readline-using programs), and has to be defined using Bash's bind builtin, specifically, the -x option:

bind -m vi-command -x '"\C-h": tmux select-pane -L'

Zsh

Zsh's ZLE is different, in that it is specifically part of the actual zsh shell, but it also doesn't have a straightforward "execute command" option. Instead, you have to define a custom ZLE widget, which can only call a shell function, and then bind that to a key.

  1. Define a function that runs the thing.

    tmux-go-left() { tmux select-pane -L; }
    

    When running an interactive program, its stdin must be redirected from /dev/tty (otherwise it'll read EOF and immediately quit), and zle -I must be called to "invalidate" the screen contents when the program exits (otherwise the cursor will be in the wrong location). For example:

    open-htop() { htop </dev/tty; zle -I; }
    
  2. Define a widget that calls the function.

    zle -N tmux-go-left
    zle -N open-htop
    

    If the function name is not provided, it's assumed to be the same as the widget name.

  3. Bind a key to the widget.

    bindkey -a '\C-h' tmux-go-left
    bindkey -v '\C-p' open-htop
    

    It seems that -v selects Vi insert mode; -a selects Vi command mode.

Sources:

Related Question