diff options
Diffstat (limited to 'bin/menuscripts/commander')
-rwxr-xr-x | bin/menuscripts/commander | 313 |
1 files changed, 313 insertions, 0 deletions
diff --git a/bin/menuscripts/commander b/bin/menuscripts/commander new file mode 100755 index 0000000..028e8a7 --- /dev/null +++ b/bin/menuscripts/commander @@ -0,0 +1,313 @@ +#!/bin/sh + +# An attempt to unify usage of multiple launchers. +# MENUCMD must be set to the name of the lancher +# +# look at the last line to understand how it works + +tmp="$(mktemp -u)" +export menuopts="" +TOFIRC="$HOME/.config/tofi/config" + +options=' +horizontal +center +input +instant +dynamic +long +prompt +numbered +prefix' + +cleanup() { rm -f "$tmp"; } +logn() { >&2 printf '%s\n' "$@"; } + +run() { + IFS=: + set -f + find -L $PATH -type f -printf "%f\n" 2> /dev/null | sort -u +} + +help() { + cat <<-EOF + Usage: commander OPTIONS... + + An attempt to regroup multiple launchers into one, + it detects the value of the MENUCMD variable + + try: + MENUCMD=tofi commander < /etc/passwd + + Options: + -h Display items horizontally + -c Display centered + -i Take an input and return it to stdout + -d Adjust size and style dynamically + -p ARG Prompt user with the specified argument + -l Display in long list format + -n Output the number of matches + -r Select an executable from PATH + -s Invert instant select on single match + -x Invert prefix matching + EOF +} + +add_option() { menuopts="$menuopts $*"; } +get_prop() { awk -F '=' "/$1 *=*/ {print \$2}" "$TOFIRC"; } + + +trap cleanup EXIT + +# Helper functions +case "$MENUCMD" in + "tofi") + # $1: items count + get_height() + { + font_size="$(get_prop "font-size")" + padding_top="$(get_prop "padding-top")" + padding_bottom="$(get_prop "padding-bottom")" + + printf "%s" "$(( + font_size*2 + padding_top + padding_bottom + 2 + + ($1)*(font_size*2 - 2) + ))" + + } + # $1: items length + get_width() + { + font_size="$(get_prop "font-size")" + padding_left="$(get_prop "padding-left")" + padding_right="$(get_prop "padding-right")" + printf "%s" "$(($1*(font_size-2) + 2 + padding_left + padding_right))" + } ;; + "dmenu") ;; + *) ;; +esac + + +main() +{ + # shellcheck disable=SC2317 + case "$MENUCMD" in + "tofi") + center() { add_option "--anchor=center --width=20%"; } + + horizontal() { + add_option "--horizontal=true --height=32" + add_option "--result-spacing=12" + add_option "--selection-background=#88c0d0" + add_option "--selection-background-padding=6,4" + add_option "--padding-top=0 --padding-bottom=0" + add_option "--margin-top=4" + } + + dynamic() { + pre_cmd() + { + max_height="$(get_height 8)" + max_width="$(get_width 48)" + + tee "$tmp" + + items_count="$(wc -l < "$tmp")" + items_length="$(wc -L < "$tmp")" + + if [ "$long" -ne 1 ] + then + height="$(get_height "$items_count")" + [ "$height" -gt "$max_height" ] && height="$max_height" + add_option "--height=$height" + fi + + width="$(get_width "$items_length")" + [ "$width" -gt "$max_width" ] && width="$max_width" + + + if [ "$prompt" -eq 1 ] + then + prompt_width="$(printf "%s" "$prompt_arg" | wc -c)" + width="$((width + $(get_width "$prompt_width")))" + fi + + add_option "--width=$width" + } + } + + long() { add_option "--width=100% --height=$(get_height 20)"; } + + input() { + add_option "--height=$(get_height 0) --width=$(get_width 24)" + pre_filter() { cat /dev/null; } + } + + prefix() { add_option '--matching-algorithm=normal'; } + + instant() { add_option "--auto-accept-single=false"; } + + prompt() { add_option '--prompt-text' "$prompt_arg"; } + + numbered() { + pre_filter() { awk '{print NR, $0}'; } + post_filter() { awk '{print $1}'; } + } + + menucmd() { tofi "$@"; } + ;; + + "dmenu") + horizontal() { add_option "-l 0"; } + + center() { add_option "-c"; } + + long() { add_option "-l 20 -g 1"; } + + input() { + pre_filter() { cat /dev/null; } + } + + dynamic() { + pre_cmd() + { + tee "$tmp" + items_count="$(wc -l < "$tmp")" + number="$items_count" + + for i in $(seq $((number/2))) + do [ "$((number%i))" -eq 0 ] && factors="$i $factors" + done + + min_diff=9999999999 + for factor in $factors + do + quotient="$((number/factor))" + diff=$((quotient - factor)) + if [ "$diff" -ge 0 ] && [ "$diff" -lt "$min_diff" ] + then + columns="$factor" + rows="$quotient" + min_diff="$diff" + fi + done + + add_option "-g $columns" + add_option "-l $rows" + } + } + + instant() { add_option "-n"; } + + prefix() { add_option '-x'; } + + prompt() { add_option '-p' "$prompt_arg"; } + + numbered() { add_option "-px"; } + + menucmd() { dmenu "$@"; } + ;; + + *) + center() { :; } + + horizontal() { :; } + + dynamic() { :; } + + long() { :; } + + input() { + pre_filter() { cat /dev/null; } + add_option '--print-query' + } + + prefix() { :; } + + prompt() { add_option "--prompt" "$prompt_arg"; } + + numbered() { + pre_filter() { awk '{print NR, $0}'; } + add_option '--with-nth' '2..' + post_filter() { awk '{print $1}'; } + } + + menucmd() { fzf "$@"; } + ;; + esac + + for option in $options + do eval "$option=0" + done + + while getopts ":cdhilop:nrsx" opt + do + # shellcheck disable=SC2034 + case $opt in + + # display horizontal + h) horizontal=1 ;; + # display centered + c) center=1 ;; + # take an input and return it on stdout + i) input=1 ;; + # adjust size and style dynamically + d) dynamic=1 ;; + p) prompt=1; prompt_arg="$OPTARG";; + # long list format + l) long=1 ;; + # output number of match + n) numbered=1 ;; + # select an executable from PATH + r) shift + run | $0 "$@" + exit ;; + # invert instant select on single match + s) instant=1 ;; + # invert prefix matching + x) prefix=1 ;; + + :) + logn "Option '-$OPTARG' requires an argument" + help + exit 1 ;; + ?) + logn "Invalid option: -$OPTARG" + help + exit 1 ;; + esac + done + + + # conflicts + [ "$input" -eq 1 ] && [ "$dynamic" -eq 1 ] && logn "conflicting options." && help && exit 1 + + # quit if stdin is empty + [ -t 0 ] && [ "$input" -eq 0 ] && logn "Stdin is empty." && help && exit 1 + + # call options + for option in $options + do eval "test \"\$$option\" -eq 1" && $option + done + + command -v pre_filter > /dev/null || pre_filter() { cat; } + command -v post_filter > /dev/null || post_filter() { cat; } + + which "${MENUCMD:-fzf}" > /dev/null || exit 1 + + + + if command -v pre_cmd > /dev/null + then + pre_cmd > "$tmp" + >&2 printf "menuopts: %s\n" "$menuopts" + # shellcheck disable=SC2086 + pre_filter < "$tmp" | menucmd $menuopts | post_filter + else + >&2 printf "menuopts: %s\n" "$menuopts" + # shellcheck disable=SC2086 + pre_filter | menucmd $menuopts | post_filter + fi +} + +main "$@" |