TheRepoClub-DotFiles/.local/bin/rofi/powermenu
2024-08-20 18:25:13 +01:00

264 lines
7.7 KiB
Bash
Executable File

#!/usr/bin/env bash
#-*-coding:utf-8 -*-
#Auto updated?
# Yes
#File:
# powermenu
#Author:
# The-Repo-Club [wayne6324@gmail.com]
#Github:
# https://github.com/The-Repo-Club/
#
#Created:
# Wed 07 December 2022, 11:01:52 PM [GMT]
#Modified:
# Sat 02 September 2023, 12:11:51 AM [GMT+1]
#
#Description:
# This script defines just a mode for rofi instead of being a self-contained
# executable that launches rofi by itself. This makes it more flexible than
# running rofi inside this script as now the user can call rofi as one pleases.
# For instance:
#
# rofi -show powermenu -config ~/.config/rofi/powermenu.rasi
#
#Dependencies:
# <None>
#
# shellcheck disable=all
if [ -z "${ROFI_OUTSIDE}" ]; then
echo "run this script in rofi".
exit
fi
set -e
set -u
# All supported choices
all=(shutdown reboot suspend hibernate logout lockscreen)
# By default, show all (i.e., just copy the array)
show=("${all[@]}")
declare -A texts
texts[lockscreen]="lock screen"
texts[logout]="log out"
texts[suspend]="suspend"
texts[hibernate]="hibernate"
texts[reboot]="reboot"
texts[shutdown]="shut down"
declare -A icons
icons[lockscreen]=""
icons[logout]="󰍃"
icons[suspend]="󰒲"
icons[hibernate]="󰋊"
icons[reboot]="󰜉"
icons[shutdown]="󰐥"
icons[cancel]=""
declare -A actions
actions[lockscreen]="loginctl lock-session"
actions[logout]="pkill -KILL -u ${USER}"
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
getuptime() {
state=$(uptime | sed -E 's/^[^,]*up *//; s/mins/minutes/; s/hrs?/hours/;
s/([[:digit:]]+):0?([[:digit:]]+)/\1 hours, \2 minutes/;
s/^1 hours/1 hour/; s/ 1 hours/ 1 hour/;
s/min,/minutes,/; s/ 0 minutes,/ less than a minute,/; s/ 1 minutes/ 1 minute/;
s/ / /; s/, *[[:digit:]]* users?.*//')
}
function check_valid {
option="$1"
shift 1
for entry in "${@}"; do
if [ -z "${actions[$entry]+x}" ]; then
echo "Invalid choice in $option: $entry" >&2
exit 1
fi
done
}
# Parse command-line options
parsed=$(getopt --options=h --longoptions=help,dry-run,confirm:,choices:,choose:,symbols,no-symbols --name "$0" -- "$@")
if [ $? -ne 0 ]; then
echo 'Terminating...' >&2
exit 1
fi
eval set -- "$parsed"
unset parsed
while true; do
case "$1" in
"-h" | "--help")
echo "rofi-power-menu - a power menu mode for Rofi"
echo
echo "Usage: rofi-power-menu [--choices CHOICES] [--confirm CHOICES]"
echo " [--choose CHOICE] [--dry-run] [--symbols|--no-symbols]"
echo
echo "Use with Rofi in script mode. For instance, to ask for shutdown or reboot:"
echo
echo " rofi -show menu -modi \"menu:rofi-power-menu --choices=shutdown/reboot\""
echo
echo "Available options:"
echo " --dry-run Don't perform the selected action but print it to stderr."
echo " --choices CHOICES Show only the selected choices in the given order. Use / "
echo " as the separator. Available choices are lockscreen, logout,"
echo " suspend, hibernate, reboot and shutdown. By default, all"
echo " available choices are shown."
echo " --confirm CHOICES Require confirmation for the gives choices only. Use / as"
echo " the separator. Available choices are lockscreen, logout,"
echo " suspend, hibernate, reboot and shutdown. By default, only"
echo " irreversible actions logout, reboot and shutdown require"
echo " confirmation."
echo " --choose CHOICE Preselect the given choice and only ask for a confirmation"
echo " (if confirmation is set to be requested). It is strongly"
echo " recommended to combine this option with --confirm=CHOICE"
echo " if the choice wouldn't require confirmation by default."
echo " Available choices are lockscreen, logout, suspend,"
echo " hibernate, reboot and shutdown."
echo " --[no-]symbols Show Unicode symbols or not. Requires a font with support"
echo " for the symbols. Use, for instance, fonts from the"
echo " Nerdfonts collection. By default, they are shown"
echo " -h,--help Show this help text."
exit 0
;;
"--dry-run")
dryrun=true
shift 1
;;
"--confirm")
IFS='/' read -ra confirmations <<<"$2"
check_valid "$1" "${confirmations[@]}"
shift 2
;;
"--choices")
IFS='/' read -ra show <<<"$2"
check_valid "$1" "${show[@]}"
shift 2
;;
"--choose")
# Check that the choice is valid
check_valid "$1" "$2"
selectionID="$2"
shift 2
;;
"--symbols")
showsymbols=true
shift 1
;;
"--no-symbols")
showsymbols=false
shift 1
;;
"--")
shift
break
;;
*)
echo "Internal error" >&2
exit 1
;;
esac
done
# Define the messages after parsing the CLI options so that it is possible to
# configure them in the future.
function write_message {
icon="<span font_size=\"medium\">$1</span>"
text="<span font_size=\"medium\">$2</span>"
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"
echo -e "\0markup-rows\x1ftrue"
if [ -z "${selection+x}" ]; then
getuptime
echo -e "\0prompt\x1fPower Menu"
echo -en "\0message\x1fUptime :: ${state^}\n"
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