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 "$@"  | 
