#!/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/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 '"$*"' < "$term_menu_tmp" $input EOF' & cat < "$term_menu_tmp"