-
-
Save thinkryan/bca77d88958562a54da6d84cd6ae0e70 to your computer and use it in GitHub Desktop.
Fish fzf settings & functions
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
## FZF settings & functions for fish; collected with attribution and modified. | |
# These rely on `git lg`; from git's config: | |
# lg = log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' | |
# They also rely on the following being installed: | |
# - bat | |
# - choose | |
# - delta | |
# - exa | |
# - fd | |
# - rg | |
# https://github.com/jethrokuan/fzf | |
# https://github.com/junegunn/fzf#respecting-gitignore | |
# We want hidden but not `.git` paths | |
set -gx FZF_DEFAULT_COMMAND "fd --hidden --no-ignore --follow --exclude='**/.git/'" | |
# https://github.com/junegunn/fzf/wiki/Examples#clipboard | |
# `--min-height` is useful with tiny terminal windows; e.g. for VSCode, | |
# especially when the preview window is important, like in git log. | |
# TODO: could we use | |
# https://github.com/fish-shell/fish-shell/blob/master/share/functions/fish_clipboard_copy.fish | |
# to allow this to work on multiple platforms? | |
set -gx FZF_DEFAULT_OPTS '--height 50% --min-height=30 --layout=reverse --color=light | |
--bind="ctrl-y:execute-silent(printf {} | cut -f 2- | pbcopy)" | |
--bind=ctrl-u:preview-half-page-up | |
--bind=ctrl-d:preview-half-page-down' | |
set -gx FZF_CTRL_T_COMMAND $FZF_DEFAULT_COMMAND "--type=f" | |
set -gx FZF_CTRL_T_OPTS "--preview='bat --style=numbers --color=always {}'" | |
set -gx FZF_ALT_C_COMMAND $FZF_DEFAULT_COMMAND "--type=d" | |
set -gx FZF_ALT_C_OPTS "--preview='exa -T {}'" | |
# https://github.com/junegunn/fzf/wiki/Configuring-shell-key-bindings | |
set -gx FZF_CTRL_R_OPTS "--preview='echo {}' --preview-window=down:3:hidden:wrap --bind='?:toggle-preview'" | |
# Heavily adapted & simplified from: | |
# https://github.com/junegunn/fzf/wiki/Examples-(fish)#navigation | |
function fzf-cdhist-widget -d 'cd to one of the previously visited locations' | |
if [ -z "$dirprev" ] | |
return | |
end | |
# TODO @max: Can we re-include git-ignored folders? | |
string join \n $dirprev | tac | eval (__fzfcmd) +m --tiebreak=index --toggle-sort=ctrl-r $FZF_CDHIST_OPTS | read -l result | |
[ "$result" ]; and cd $result | |
commandline -f repaint | |
end | |
# Significantly adjusted to fish from | |
# https://github.com/junegunn/fzf/wiki/Examples#searching-file-contents | |
function fzf-rg-search-widget -d 'find text in files' | |
set rg_command "rg --ignore-case --files-with-matches -uu --iglob='!**/.git/' --follow" | |
# Start with all files; i.e. .* | |
FZF_DEFAULT_COMMAND="$rg_command '.*'" SHELL=fish fzf \ | |
-m \ | |
-e \ | |
--ansi \ | |
--disabled \ | |
--bind "change:reload:$rg_command {q} || true" \ | |
# I'm not sure what this `cut` does — but remove it and the whole thing fails. | |
--preview "rg -i --pretty --context 2 {q} {}" | cut -d":" -f1,2 \ | |
| fzf_add_to_commandline | |
end | |
# The following few `__git` functions are Heavily adapted from | |
# https://gist.github.com/aluxian/9c6f97557b7971c32fdff2f2b1da8209 | |
function __git_fzf_is_in_git_repo -d "Check whether we're in a git repo" | |
command -s -q git | |
and git rev-parse HEAD >/dev/null 2>&1 | |
end | |
# Deciphered from fzf-file-widget. Somewhat unclear why it doesn't exist already! | |
function fzf_add_to_commandline -d 'add stdin to the command line, for fzf functions' | |
read -l -z result | |
commandline -t "" | |
# Do we need to escape this? This was here before, but doesn't work well with | |
# multiline strings. | |
# commandline -it -- (string escape $result) | |
commandline -it -- (echo $result | paste -s -d" " -) | |
commandline -f repaint | |
end | |
# Because files that are tracked / untracked have different forms, we can't | |
# currently _select_ files that are untracked — selecting them won't print | |
# anything to the command line. | |
function __git_fzf_git_status -d "fzf on files from git status" | |
__git_fzf_is_in_git_repo; or return | |
# We use porcelain since otherwise it's hard to handle files with quotes. We | |
# lose the colors. | |
# | |
# The previous version was this, which didn't work for files with spaces: | |
# fzf -m --ansi --preview "git diff HEAD -- {} | delta" | \ | |
# Another previous version did this, which gives some info about whether | |
# it's added etc, but fails for new files, since their porcelain output is | |
# different. | |
# git status --porcelain=2 | choose -1 | \ | |
# | |
git status --porcelain=2 | choose 1 8: \ | |
# We could use the field indexers, but it means we have a different command | |
# for the index and the next command in the pipe. ref | |
# https://github.com/junegunn/fzf/issues/1323. | |
# SHELL=fish fzf -m --ansi --preview "git diff HEAD -- {-1} | delta" | \ | |
| SHELL=fish fzf -m --ansi --preview "git diff HEAD -- (echo {} | choose -1 ) | delta" \ | |
--bind=ctrl-a:"execute-silent(git add {-1})+abort" \ | |
| choose -1 \ | |
| fzf_add_to_commandline | |
commandline -f repaint | |
end | |
function __get_branch -d "Parses branch name for __git_fzf_git_branch" | |
read | rg '[\*\s]*(?:remotes/)?([^s]*)' -r '$1' | |
end | |
function __git_fzf_git_branch -d "fzf on git branches" | |
__git_fzf_is_in_git_repo; or return | |
# We could use this rather than the separate function, but we get quoting issues. | |
# set pattern '[\*\s]*(?:remotes/)?([^s]*)' | |
git branch -a --color=always \ | |
| grep -v '/HEAD\s' \ | |
| SHELL=fish fzf -m --ansi --preview-window=right:70% \ | |
--preview='git lg --color=always (echo {} | __get_branch)' \ | |
# This doesn't seem to print anything at all | |
--bind=ctrl-s:"execute-silent(git switch (echo {} | __get_branch) > /dev/tty )+abort" \ | |
| __get_branch \ | |
| fzf_add_to_commandline | |
commandline -f repaint | |
end | |
function __git_fzf_git_tag -d "fzf on git tags" | |
__git_fzf_is_in_git_repo; or return | |
git tag --sort=-creatordate \ | |
| SHELL=fish fzf -m --ansi --no-sort \ | |
--preview-window=right:70% --preview='git show {} | delta' \ | |
| fzf_add_to_commandline | |
end | |
function __git_fzf_git_log -d "fzf on git history" | |
__git_fzf_is_in_git_repo; or return | |
git lg --color=always \ | |
| SHELL=fish fzf -m --ansi --no-sort --preview 'git show (echo {} | rg "(\w+).*" -or \'$1\') | delta' \ | |
| rg "(\w+).*" -or '$1' \ | |
| fzf_add_to_commandline | |
end | |
function __git_fzf_git_stash -d "fzf on git stashes" | |
__git_fzf_is_in_git_repo; or return | |
set -l pattern "(stash@[{\d}]*)" | |
git stash list --color=always \ | |
# We seem to need delta explicitly, since git will write without using | |
# delta if it's not a tty. | |
| SHELL=fish fzf -m --ansi --no-sort \ | |
--preview "git stash show -p (echo {} | rg '$pattern' -o) | delta" \ | |
# This doesn't clear the fzf screen, so the output looks messy. Is there a | |
# better way? Adding `clear-screen+` doesn't help. | |
--bind=ctrl-p:"execute-silent(git stash pop (echo {} | rg '$pattern' -o) > /dev/tty)+abort" \ | |
| rg $pattern -o \ | |
| fzf_add_to_commandline | |
commandline -f repaint | |
end | |
function git_fzf_key_bindings -d "Set custom key bindings for git+fzf" | |
# `-M insert` is added, as we want these in insert mode | |
# | |
bind -M insert \cg\cb __git_fzf_git_branch | |
# bind -M insert \cg\cd __git_fzf_git_diff | |
bind -M insert \cg\ch __git_fzf_git_stash | |
bind -M insert \cg\cl __git_fzf_git_log | |
bind -M insert \cg\cs __git_fzf_git_status | |
bind -M insert \cg\ct __git_fzf_git_tag | |
end | |
bind \cb fzf-cdhist-widget | |
bind -M insert \cb fzf-cdhist-widget | |
bind \cf fzf-rg-search-widget | |
bind -M insert \cf fzf-rg-search-widget | |
git_fzf_key_bindings | |
# Keep an eye on https://github.com/PatrickF1/fzf.fish, which does some of | |
# these, but arguably worse. | |
### End of fzf functions |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment