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-rto the functionfzf_history. The-xoption allows bound functions to execute shell commands, in this case changing theREADLINE_LINEandREADLINE_POINTvariables.
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.