misc-scripts/fzfmenu

48 lines
1.7 KiB
Bash
Executable File

#!/bin/sh
set -euf
# fzfmenu: a dmenu replacement with fzf and a terminal emulator
# I know like 300 of these projects already exist but I wrote this for funsies
#
# usage: fzfmenu [-p PROMPT] [--] [arg...]
#
# all the args to this script get passed directly to fzf. -p is just a dmenu-compatible prompt setter, since fzf doesn't have -p
# works just like dmenu: reads stdin, splits on newlines (unless you use --read0), prints selection to stdout
# if you want shift+enter-esque functionality, I recommend adding '--bind ctrl-space:print-query+abort' to your FZF_DEFAULT_OPTS (shift+enter isn't compatible with every terminal)
# floating_terminal shouldn't have any spaces, tabs, or newlines, so no need to escape the arguments
# I put a -name here for urxvt so my window manager can center+ontop it. change as necessary/wanted
FLOATING_TERMINAL="${FLOATING_TERMINAL:-urxvt -name FLOATING_TERMINAL}"
clean() {
[ -p "${term_menu_tmp:-}" ] && rm "$term_menu_tmp"
}
if getopts :p: OPT; then
case $OPT in
p) set -- "$@" "--prompt" "$OPTARG > " && shift 2 ;; # convert to fzf-compatible --prompt
*) : ;; # simply ignore any other options cuz they might just be fzf options
esac
fi
# escape the cli arguments cuz they get passed to the nested sh
for arg; do
set -- "$@" "'$(printf "%s" "$arg" | sed "s/'/'\\\\''/g")'"
shift
done
# all of this shit can be replaced by one line
# "$TERMINAL" -e sh -c 'fzf </proc/'"$$"'/fd/0 >/proc/'"$$"'/fd/1'
# but that isn't portable (linux only). this implementation is. still cool to see though
trap 'clean' INT HUP QUIT EXIT
export input="$(cat)"
export term_menu_tmp="$(mktemp -u -t term-menu.XXXX)"
mkfifo "$term_menu_tmp"
$FLOATING_TERMINAL -e sh -c 'fzf '"$*"' <<EOF > "$term_menu_tmp"
$input
EOF' &
cat < "$term_menu_tmp"