#!/usr/bin/env bash set -e set -u # All supported choices # all=(shutdown reboot suspend hibernate logout lockscreen) all=(shutdown reboot suspend hibernate logout ) # By default, show all (i.e., just copy the array) show=("${all[@]}") declare -A texts #texts[lockscreen]="lock screen" texts[logout]="logout" texts[suspend]="suspend" texts[hibernate]="hibernate" texts[reboot]="reboot" texts[shutdown]="shutdown" declare -A icons # icons[lockscreen]="\uf023" icons[logout]="\uf842" icons[suspend]="\uf9b1" icons[hibernate]="\uf7c9" icons[reboot]="\ufc07" icons[shutdown]="\uf011" icons[cancel]="\u00d7" declare -A actions #actions[lockscreen]="sh $HOME/.config/sway/swaylock.sh" actions[logout]="i3-msg exit, mode \"default\"" #actions[logout]="loginctl terminate-session ${XDG_SESSION_ID-}" actions[suspend]="systemctl suspend" actions[hibernate]="systemctl hibernate" actions[reboot]="systemctl reboot" actions[shutdown]="systemctl poweroff" # By default, ask for confirmation for actions that are irreversible confirmations=(reboot shutdown logout) # By default, no dry run dryrun=false showsymbols=true function check_valid { option="$1" shift 1 for entry in "${@}" do if [ -z "${actions[$entry]+x}" ] then echo "Invalid choice in $1: $entry" >&2 exit 1 fi done } # Define the messages after parsing the CLI options so that it is possible to # configure them in the future. function write_message { icon="$1" text="$2" if [ "$showsymbols" = "true" ] then echo -n "\u200e$icon \u2068$text\u2069" else echo -n "$text" fi } function print_selection { echo -e "$1" | $(read -r -d '' entry; echo "echo $entry") } declare -A messages declare -A confirmationMessages for entry in "${all[@]}" do messages[$entry]=$(write_message "${icons[$entry]}" "${texts[$entry]^}") done for entry in "${all[@]}" do confirmationMessages[$entry]=$(write_message "${icons[$entry]}" "Yes, ${texts[$entry]}") done confirmationMessages[cancel]=$(write_message "${icons[cancel]}" "No, cancel") if [ $# -gt 0 ] then # If arguments given, use those as the selection selection="${@}" else # Otherwise, use the CLI passed choice if given if [ -n "${selectionID+x}" ] then selection="${messages[$selectionID]}" fi fi # Don't allow custom entries echo -e "\0no-custom\x1ftrue" # Use markup echo -e "\0markup-rows\x1ftrue" if [ -z "${selection+x}" ] then echo -e "\0prompt\x1fPower menu" for entry in "${show[@]}" do echo -e "${messages[$entry]}\0icon\x1f${icons[$entry]}" done else for entry in "${show[@]}" do if [ "$selection" = "$(print_selection "${messages[$entry]}")" ] then # Check if the selected entry is listed in confirmation requirements for confirmation in "${confirmations[@]}" do if [ "$entry" = "$confirmation" ] then # Ask for confirmation echo -e "\0prompt\x1fAre you sure" echo -e "${confirmationMessages[$entry]}\0icon\x1f${icons[$entry]}" echo -e "${confirmationMessages[cancel]}\0icon\x1f${icons[cancel]}" exit 0 fi done # If not, then no confirmation is required, so mark confirmed selection=$(print_selection "${confirmationMessages[$entry]}") fi if [ "$selection" = "$(print_selection "${confirmationMessages[$entry]}")" ] then if [ $dryrun = true ] then # Tell what would have been done echo "Selected: $entry" >&2 else # Perform the action ${actions[$entry]} fi exit 0 fi if [ "$selection" = "$(print_selection "${confirmationMessages[cancel]}")" ] then # Do nothing exit 0 fi done # The selection didn't match anything, so raise an error echo "Invalid selection: $selection" >&2 exit 1 fi