zsh: use a custom command for fzf ZLE widgets

Notable differences to the default command shipped with fzf:

  - I want to see hidden files, but not directories (the default hides
    both).
  - I want to exclude some directories on my Mac home, which are too
    large and make the find command really slow. Plus, I never want to
    dig into those directories with this method anyway.
This commit is contained in:
Fernando Schauenburg 2024-07-28 18:45:21 +02:00
parent 3949848924
commit 745b5b2fd5
2 changed files with 65 additions and 19 deletions

View file

@ -147,7 +147,6 @@ setup_zle() {
############################# #############################
# ZLE Widgets # ZLE Widgets
############################# #############################
set-cursor-shape() { set-cursor-shape() {
local block='\e[1 q' # blinking block local block='\e[1 q' # blinking block
local underline='\e[3 q' # blinking underline, 4 for steady local underline='\e[3 q' # blinking underline, 4 for steady
@ -225,13 +224,8 @@ setup_zle() {
############################# #############################
# fzf # fzf
############################# #############################
if type -p fzf >/dev/null; then if type -p fzf >/dev/null; then
local fzf_config="$ZDOTDIR/fzf-key-bindings.zsh" setup_zle_fzf
[ -r "$fzf_config" ] && source "$fzf_config"
export FZF_CTRL_T_OPTS=--border-label='" Select file(s) "'
export FZF_CTRL_R_OPTS=--border-label='" History search "'
export FZF_ALT_C_OPTS=--border-label='" Change directory "'
else else
# Fall back to incremental search # Fall back to incremental search
bindkey -M viins '^r' history-incremental-search-backward bindkey -M viins '^r' history-incremental-search-backward
@ -241,6 +235,55 @@ setup_zle() {
fi fi
} }
setup_zle_fzf() {
local fzf_config="$ZDOTDIR/fzf/key-bindings.zsh"
[ -r "$fzf_config" ] || return
fzf_find() {
local excluded_dirs=("-name '.*'") # Exclude hidden directories.
if [ "$(uname -s)" = "Darwin" ] && [ "$(pwd)" = "$HOME" ]; then
# These macOS directories would make the find command unusable (too slow).
excluded_dirs+=(
"-name Library"
"-name Movies"
"-name Music"
"-name Pictures"
)
fi
local excluded_filesystems=(
"-fstype devfs"
"-fstype devtmpfs"
"-fstype proc"
"-fstype sysfs"
)
local excluded_items=(
"-type d \\( ${(j: -o :)excluded_dirs} \\)"
"${(j: -o :)excluded_filesystems}"
)
local excluded="\\( ${(j: -o :)excluded_items} \\) -prune"
local included="\\( ${(j: -o :)@} \\) -print"
eval "command find -L . -mindepth 1 $excluded -o $included 2>/dev/null | cut -c3-"
}
fzf_find_files() {
fzf_find "-type d" "-type f"
}
fzf_find_dirs() {
fzf_find "-type d"
}
source "$fzf_config"
export FZF_CTRL_T_COMMAND=fzf_find_files
export FZF_ALT_C_COMMAND=fzf_find_dirs
export FZF_CTRL_T_OPTS=--border-label='" Select file(s) "'
export FZF_CTRL_R_OPTS=--border-label='" History search "'
export FZF_ALT_C_OPTS=--border-label='" Change directory "'
}
# Colorful man pages. # Colorful man pages.
setup_man_pages() { setup_man_pages() {
# Foreground colors # Foreground colors

View file

@ -11,6 +11,9 @@
# - $FZF_ALT_C_COMMAND # - $FZF_ALT_C_COMMAND
# - $FZF_ALT_C_OPTS # - $FZF_ALT_C_OPTS
[[ -o interactive ]] || return 0
# Key bindings # Key bindings
# ------------ # ------------
@ -32,21 +35,19 @@ else
} }
fi fi
'emulate' 'zsh' '-o' 'no_aliases' 'builtin' 'emulate' 'zsh' && 'builtin' 'setopt' 'no_aliases'
{ {
[[ -o interactive ]] || return 0
# CTRL-T - Paste the selected file path(s) into the command line # CTRL-T - Paste the selected file path(s) into the command line
__fsel() { __fsel() {
local cmd="${FZF_CTRL_T_COMMAND:-"command find -L . -mindepth 1 \\( -path '*/\\.*' -o -fstype 'sysfs' -o -fstype 'devfs' -o -fstype 'devtmpfs' -o -fstype 'proc' \\) -prune \ local cmd="${FZF_CTRL_T_COMMAND:-"command find -L . -mindepth 1 \\( -path '*/.*' -o -fstype 'sysfs' -o -fstype 'devfs' -o -fstype 'devtmpfs' -o -fstype 'proc' \\) -prune \
-o -type f -print \ -o -type f -print \
-o -type d -print \ -o -type d -print \
-o -type l -print 2> /dev/null | cut -b3-"}" -o -type l -print 2> /dev/null | cut -b3-"}"
setopt localoptions pipefail no_aliases 2> /dev/null setopt localoptions pipefail no_aliases 2> /dev/null
local item local item
eval "$cmd" | FZF_DEFAULT_OPTS="--height ${FZF_TMUX_HEIGHT:-40%} --reverse --bind=ctrl-z:ignore ${FZF_DEFAULT_OPTS-} ${FZF_CTRL_T_OPTS-}" $(__fzfcmd) -m "$@" | while read item; do eval "$cmd" | FZF_DEFAULT_OPTS="--height ${FZF_TMUX_HEIGHT:-40%} --reverse --scheme=path --bind=ctrl-z:ignore ${FZF_DEFAULT_OPTS-} ${FZF_CTRL_T_OPTS-}" $(__fzfcmd) -m "$@" | while read item; do
echo -n "${(q)item} " echo -n "${(q)item} "
done done
local ret=$? local ret=$?
@ -72,10 +73,10 @@ bindkey -M viins '^T' fzf-file-widget
# ALT-C - cd into the selected directory # ALT-C - cd into the selected directory
fzf-cd-widget() { fzf-cd-widget() {
local cmd="${FZF_ALT_C_COMMAND:-"command find -L . -mindepth 1 \\( -path '*/\\.*' -o -fstype 'sysfs' -o -fstype 'devfs' -o -fstype 'devtmpfs' -o -fstype 'proc' \\) -prune \ local cmd="${FZF_ALT_C_COMMAND:-"command find -L . -mindepth 1 \\( -path '*/.*' -o -fstype 'sysfs' -o -fstype 'devfs' -o -fstype 'devtmpfs' -o -fstype 'proc' \\) -prune \
-o -type d -print 2> /dev/null | cut -b3-"}" -o -type d -print 2> /dev/null | cut -b3-"}"
setopt localoptions pipefail no_aliases 2> /dev/null setopt localoptions pipefail no_aliases 2> /dev/null
local dir="$(eval "$cmd" | FZF_DEFAULT_OPTS="--height ${FZF_TMUX_HEIGHT:-40%} --reverse --bind=ctrl-z:ignore ${FZF_DEFAULT_OPTS-} ${FZF_ALT_C_OPTS-}" $(__fzfcmd) +m)" local dir="$(eval "$cmd" | FZF_DEFAULT_OPTS="--height ${FZF_TMUX_HEIGHT:-40%} --reverse --scheme=path --bind=ctrl-z:ignore ${FZF_DEFAULT_OPTS-} ${FZF_ALT_C_OPTS-}" $(__fzfcmd) +m)"
if [[ -z "$dir" ]]; then if [[ -z "$dir" ]]; then
zle redisplay zle redisplay
return 0 return 0
@ -97,13 +98,15 @@ bindkey -M viins '\ec' fzf-cd-widget
fzf-history-widget() { fzf-history-widget() {
local selected num local selected num
setopt localoptions noglobsubst noposixbuiltins pipefail no_aliases 2> /dev/null setopt localoptions noglobsubst noposixbuiltins pipefail no_aliases 2> /dev/null
selected=( $(fc -rl 1 | awk '{ cmd=$0; sub(/^[ \t]*[0-9]+\**[ \t]+/, "", cmd); if (!seen[cmd]++) print $0 }' | selected="$(fc -rl 1 | awk '{ cmd=$0; sub(/^[ \t]*[0-9]+\**[ \t]+/, "", cmd); if (!seen[cmd]++) print $0 }' |
FZF_DEFAULT_OPTS="--height ${FZF_TMUX_HEIGHT:-40%} ${FZF_DEFAULT_OPTS-} -n2..,.. --tiebreak=index --reverse --bind=ctrl-r:toggle-sort,ctrl-z:ignore ${FZF_CTRL_R_OPTS-} --query=${(qqq)LBUFFER} +m" $(__fzfcmd)) ) FZF_DEFAULT_OPTS="--height ${FZF_TMUX_HEIGHT:-40%} ${FZF_DEFAULT_OPTS-} -n2..,.. --scheme=history --bind=ctrl-r:toggle-sort,ctrl-z:ignore ${FZF_CTRL_R_OPTS-} --query=${(qqq)LBUFFER} +m" $(__fzfcmd))"
local ret=$? local ret=$?
if [ -n "$selected" ]; then if [ -n "$selected" ]; then
num=$selected[1] num=$(awk '{print $1}' <<< "$selected")
if [ -n "$num" ]; then if [[ "$num" =~ '^[1-9][0-9]*\*?$' ]]; then
zle vi-fetch-history -n $num zle vi-fetch-history -n ${num%\*}
else # selected is a custom query, not from history
LBUFFER="$selected"
fi fi
fi fi
zle reset-prompt zle reset-prompt