Run external command in inputrc mapping, without modifying current line
Solution 1:
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.
-
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), andzle -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; }
-
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.
-
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:
man zshzle
- https://stackoverflow.com/questions/57539180/why-is-interactive-command-breaking-when-using-zsh-widget-to-execute-it