Skip to content

Instantly share code, notes, and snippets.

@nick133
Last active May 4, 2022 22:07
Show Gist options
  • Save nick133/72fa281b3836f8dde0d732a69bb32066 to your computer and use it in GitHub Desktop.
Save nick133/72fa281b3836f8dde0d732a69bb32066 to your computer and use it in GitHub Desktop.
FuMenu - minimalists terminal and desktop menu based on fzf, designed primarily for sway
#!/usr/bin/env /usr/bin/bash
#
# FuMenu v0.2 (2022)
# Minimalistic fzf-powered terminal menu system
#
# Features:
# * title
# * submenus
# * configurable separators
# * source for use as function
# * gui support
#
# Requirements: fzf, bash, [alacritty, sway]
#
# Config search order:
# 1. From command line option: fumenu menu.rc
# 2. '.menurc' and then 'menurc' from current working directory
# 3. $HOME/.config/menurc
#
# Example .menurc:
#
# menu_main=("〜Menu title〜"
# "+Submenu" submenu
# "Menu item 1" ex_menu_item1
# "Menu item 2" ex_menu_item2
# -
# "Menu item after separator 3" ex_menu_item3
# "Menu item 4" ex_menu_item4
# )
#
# submenu=("Submenu title"
# .. menu_main
# "Submenu item 1" ex_submenu_item1
# "Submenu item N" ex_submenu_itemN
# )
#
# ex_menu_item1() {
# action_for_item1.sh
# sleep 2
# exit 0
# }
#
#### ~config~ ####
separator=" "
# 1st symbol to mark submenu
submark="+"
subsym="𝅌"
#subsym=" 🢒"
backmark=".."
standalone=yes
#### ~guts~ ####
(return 0 2>/dev/null) && sourced=1
if [[ "$1" == "-h" ]]
then
echo -e "FuMenu v0.2 (2022)"
echo -e "Minimalistic fzf-powered terminal menu system\n"
echo -e "* Put alacritty.yml in the same dir as .menurc for terminal settings."
echo -e "* File can be sourced without execution to access fuctions only.\n"
echo -e "Usage: fumenu [-t] config.menurc"
echo -e " -h This help"
echo -e " -t Run in GUI terminal"
exit 0
elif [[ "$1" == "-t" ]]
then
menurc="$2"
terminal="alacritty"
termconfig="$(dirname $2)/alacritty.yml"
[[ -r "$termconfig" ]] && terminal+=" --config-file=$termconfig"
if [[ "$standalone" ]]
then
if pidof sway >/dev/null
then
swaymsg -t get_tree | grep -q '"name": "QuickLaunch Menu",' && beep && exit 0
else
ps -o args -C alacritty | grep -q "^$terminal .\+/fumenu .\+" && beep && exit 0
fi
fi
$terminal -e $0 $menurc 2>/dev/null &
exit 0
elif [[ -n "$1" ]]
then
menurc="$1"
fi
[[ -z "$sourced" ]] && {
declare -a rcpath
[[ -n "$menurc" ]] && rcpath+=("$menurc")
rcpath+=("./.menurc")
rcpath+=("./menurc")
rcpath+=("$HOME/.config/menurc")
for rc in "${rcpath[@]}"
do
[[ -r "$rc" ]] && {
source "$rc"
break
}
done
unset rcpath
}
fuzzy() {
local title=$1
shift
fzf -i -e +m +s --layout=reverse --info=hidden --padding 0,0,0,2 --cycle \
--bind home:page-up --bind end:page-down --border=rounded \
--header="$title" --header-lines=1 --prompt='' --pointer=' ' \
--color='gutter:#222222,pointer:#000000,header:#7777ff,border:#202020' \
--color='bg+:#7777ff,fg+:#000000,fg:#aaaaaa' $@
}
exec_menu() {
local menu_title=""
local -n menu_items=$1
local -a menu_names
local -A menu_actions
local key=
local submenu=
for i in "${menu_items[@]}"
do
if [[ -z "$menu_title" ]]
then
menu_title="$i"
elif [[ -z "$key" ]]
then
if [[ "$i" == "-" ]]
then
menu_names+=("$separator")
[[ -z "${menu_actions[$separator]}" ]] && menu_actions["$separator"]=":"
else
if [[ "${i:0:1}" == "$submark" ]]
then
submenu=true
key="${i:1}$subsym"
elif [[ "$i" == "$backmark" ]]
then
submenu=true
key="$i "
else
key="$i"
fi
menu_names+=("$key")
fi
else
if [[ -n "$submenu" ]]
then
menu_actions["$key"]="exec_menu $i"
submenu=
else
if [[ "${i:((${#i} - 1)):1}" == "&" ]]
then
menu_actions["$key"]="setsid -f ${i:0:((${#i} - 1))}"
else
menu_actions["$key"]="$i"
fi
fi
key=
fi
done
clear
# First echo for empty line between the header and items (--header-lines=1)
local selected=$(
(echo -e
for i in "${menu_names[@]}"
do echo -e "$i"
done) | fuzzy "$menu_title"
)
[[ -n "$selected" ]] && eval "${menu_actions[$selected]}"
}
[[ -z "$sourced" ]] && exec_menu menu_main || export exec_menu
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment