TIL: CTRL-R replacement with fzf
2024-02-23
- shell
Add this to .bashrc
:
fzf_history() {
READLINE_LINE=$(history | sed 's/^.\{27\}//' | fzf)
READLINE_POINT=${#READLINE_LINE}
}
bind -x '"\C-r": fzf_history'
And here’s one for zsh:
fzf_history() {
BUFFER=$(history | sed 's/^.\{7\}//' | fzf)
CURSOR=$#BUFFER
zle reset-prompt
}
zle -N fzf_history
bindkey '^R' fzf_history
That assumes 27 characters of leading junk in the history
command. I’ve found this to be variable on different machines.
This works because of the features provided by Bash’s Readline library.
READLINE_LINE
: This special variable determines the contents of the line. When you setREADLINE_LINE=$(history | sed 's/^.\{27\}//' | fzf)
, it changes the contents of the current input line to the result of the command inside$()
which is the command you select fromfzf
.READLINE_POINT
: This special variable specifies the position of the cursor. When you runREADLINE_POINT=${#READLINE_LINE}
, it sets the cursor position to the end of the current input line.bind -x '"\C-r": fzf_history'
: this bindsCtrl-r
to the functionfzf_history
. The-x
option allows bound functions to execute shell commands, in this case changing theREADLINE_LINE
andREADLINE_POINT
variables.
When Ctrl-r
is pressed, it triggers the fzf_history
function that runs the fzf
interface to choose a command from history and places it on the command line. The cursor is moved to the end of the line, ready for you to press Enter to execute the command or modify it if needed.