Bash Key Binding – Creating a Key Binding to Re-source Shell Configuration Without Saving Command in History

bashconfigurationzsh

I would like to create a key binding, using the key sequence C-x r, to reload the configuration of bash, stored in ~/.bashrc, and the one of the readline library stored in ~/.inputrc.

To reload the configuration of readline, I think I could use the re-read-init-file function which is described in man 3 readline:

re-read-init-file (C-x C-r)
        Read in the contents of the inputrc file, and incorporate any bindings or variable  assignments  found there.

To reload the configuration of bash, I could use the source or . command. However, I'm not sure what's the best way to combine a shell command with a readline function. So, I came up with the combination of 2 key bindings:

bind '"\C-xr":      ". ~/.bashrc \C-x\C-z1\C-m"'
bind '"\C-x\C-z1":  re-read-init-file'

When I hit C-x r in bash, here's what happens:

. ~/.bashrc    `~/.bashrc` is inserted on the command line
C-x C-z 1      `C-x C-z 1` is typed which is bound to `re-read-init-file`
C-m            `C-m` is hit which executes the current command line

It seems to work because, inside tmux, if I have 2 panes, one to edit ~/.inputrc or ~/.bashrc, the other with a shell, and I change a configuration file, after hitting C-x r in the shell, I can see the change taking effect (be it a new alias or a new key binding), without the need to close the pane to reopen a new shell.

But, is there a better way of achieving the same result? In particular, is it possible to execute the commands without leaving an entry in the history? Because if I hit C-p to recall the last executed command, I get . ~/.bashrc, while I would prefer to directly get the command which was executed before I re-sourced the shell configuration.

I have the same issue with zsh:

bindkey -s '^Xr' '. ~/.zshrc^M'

Again, after hitting C-x r, the command . ~/.zshrc is logged in the history. Is there a better way to re-source the config of zsh?

Best Answer

Don't inject a command into the command line to run it! That's very brittle — what you're trying assumes that there's nothing typed at the current prompt yet. Instead, bind the key to a shell command, rather than binding it to a line edition command.

In bash, use bind -x.

bind -x '"\C-xr": . ~/.bashrc'

If you also want to re-read the readline configuration, there's no non-kludgy way to mix readline commands and bash commands in a key binding. A kludgy way is to bind the key to a readline macro that contains two key sequences, one bound to the readline command you want to execute and one bound to the bash command.

bind '"\e[99i~": re-read-init-file'
bind -x '"\e[99b~": . ~/.bashrc'
bind '"\C-xr": "\e[99i~\e[99b~"'

In zsh, use zle -N to declare a function as a widget, then bindkey to bind that widget to a key.

reread_zshrc () {
  . ~/.zshrc
}
zle -N reread_zshrc
bindkey '^Xr' reread_zshrc
Related Question