dotfiles/config/rofi/rofi-power-menu (view raw)
| 1 | #!/usr/bin/env bash |
| 2 | set -e |
| 3 | set -u |
| 4 | |
| 5 | all=(shutdown reboot suspend hibernate logout lockscreen) |
| 6 | show=("${all[@]}") |
| 7 | |
| 8 | |
| 9 | declare -A texts |
| 10 | texts[lockscreen]="lock screen" |
| 11 | texts[switchuser]="switch user" |
| 12 | texts[logout]="log out" |
| 13 | texts[suspend]="suspend" |
| 14 | texts[hibernate]="hibernate" |
| 15 | texts[reboot]="reboot" |
| 16 | texts[shutdown]="shut down" |
| 17 | |
| 18 | declare -A icons |
| 19 | icons[lockscreen]="\uf023" |
| 20 | icons[switchuser]="\uf518" |
| 21 | icons[logout]="\uf842" |
| 22 | icons[suspend]="\uf9b1" |
| 23 | icons[hibernate]="\uf7c9" |
| 24 | icons[reboot]="\ufc07" |
| 25 | icons[shutdown]="\uf011" |
| 26 | icons[cancel]="\u00d7" |
| 27 | |
| 28 | declare -A actions |
| 29 | actions[lockscreen]="loginctl lock-session $XDG_SESSION_ID" |
| 30 | actions[logout]="loginctl terminate-session $XDG_SESSION_ID" |
| 31 | actions[suspend]="systemctl suspend" |
| 32 | actions[hibernate]="systemctl hibernate" |
| 33 | actions[reboot]="systemctl reboot" |
| 34 | actions[shutdown]="systemctl poweroff" |
| 35 | |
| 36 | confirmations=(reboot shutdown logout) |
| 37 | |
| 38 | dryrun=false |
| 39 | showsymbols=true |
| 40 | |
| 41 | function check_valid { |
| 42 | option="$1" |
| 43 | shift 1 |
| 44 | for entry in "${@}" |
| 45 | do |
| 46 | if [ -z "${actions[$entry]+x}" ] |
| 47 | then |
| 48 | echo "Invalid choice in $1: $entry" >&2 |
| 49 | exit 1 |
| 50 | fi |
| 51 | done |
| 52 | } |
| 53 | |
| 54 | parsed=$(getopt --options=h --longoptions=help,dry-run,confirm:,choices:,choose:,symbols,no-symbols --name "$0" -- "$@") |
| 55 | if [ $? -ne 0 ]; then |
| 56 | echo 'Terminating...' >&2 |
| 57 | exit 1 |
| 58 | fi |
| 59 | eval set -- "$parsed" |
| 60 | unset parsed |
| 61 | while true; do |
| 62 | case "$1" in |
| 63 | "-h"|"--help") |
| 64 | echo "rofi-power-menu - a power menu mode for Rofi" |
| 65 | echo |
| 66 | echo "Usage: rofi-power-menu [--choices CHOICES] [--confirm CHOICES]" |
| 67 | echo " [--choose CHOICE] [--dry-run] [--symbols|--no-symbols]" |
| 68 | echo |
| 69 | echo "Use with Rofi in script mode. For instance, to ask for shutdown or reboot:" |
| 70 | echo |
| 71 | echo " rofi -show menu -modi \"menu:rofi-power-menu --choices=shutdown/reboot\"" |
| 72 | echo |
| 73 | echo "Available options:" |
| 74 | echo " --dry-run Don't perform the selected action but print it to stderr." |
| 75 | echo " --choices CHOICES Show only the selected choices in the given order. Use / " |
| 76 | echo " as the separator. Available choices are lockscreen, logout," |
| 77 | echo " suspend, hibernate, reboot and shutdown. By default, all" |
| 78 | echo " available choices are shown." |
| 79 | echo " --confirm CHOICES Require confirmation for the gives choices only. Use / as" |
| 80 | echo " the separator. Available choices are lockscreen, logout," |
| 81 | echo " suspend, hibernate, reboot and shutdown. By default, only" |
| 82 | echo " irreversible actions logout, reboot and shutdown require" |
| 83 | echo " confirmation." |
| 84 | echo " --choose CHOICE Preselect the given choice and only ask for a confirmation" |
| 85 | echo " (if confirmation is set to be requested). It is strongly" |
| 86 | echo " recommended to combine this option with --confirm=CHOICE" |
| 87 | echo " if the choice wouldn't require confirmation by default." |
| 88 | echo " Available choices are lockscreen, logout, suspend," |
| 89 | echo " hibernate, reboot and shutdown." |
| 90 | echo " --[no-]symbols Show Unicode symbols or not. Requires a font with support" |
| 91 | echo " for the symbols. Use, for instance, fonts from the" |
| 92 | echo " Nerdfonts collection. By default, they are shown" |
| 93 | echo " -h,--help Show this help text." |
| 94 | exit 0 |
| 95 | ;; |
| 96 | "--dry-run") |
| 97 | dryrun=true |
| 98 | shift 1 |
| 99 | ;; |
| 100 | "--confirm") |
| 101 | IFS='/' read -ra confirmations <<< "$2" |
| 102 | check_valid "$1" "${confirmations[@]}" |
| 103 | shift 2 |
| 104 | ;; |
| 105 | "--choices") |
| 106 | IFS='/' read -ra show <<< "$2" |
| 107 | check_valid "$1" "${show[@]}" |
| 108 | shift 2 |
| 109 | ;; |
| 110 | "--choose") |
| 111 | check_valid "$1" "$2" |
| 112 | selectionID="$2" |
| 113 | shift 2 |
| 114 | ;; |
| 115 | "--symbols") |
| 116 | showsymbols=true |
| 117 | shift 1 |
| 118 | ;; |
| 119 | "--no-symbols") |
| 120 | showsymbols=false |
| 121 | shift 1 |
| 122 | ;; |
| 123 | "--") |
| 124 | shift |
| 125 | break |
| 126 | ;; |
| 127 | *) |
| 128 | echo "Internal error" >&2 |
| 129 | exit 1 |
| 130 | ;; |
| 131 | esac |
| 132 | done |
| 133 | |
| 134 | function write_message { |
| 135 | icon="<span font_size=\"medium\">$1</span>" |
| 136 | text="<span font_size=\"medium\">$2</span>" |
| 137 | if [ "$showsymbols" = "true" ] |
| 138 | then |
| 139 | echo -n "\u200e$icon \u2068$text\u2069" |
| 140 | else |
| 141 | echo -n "$text" |
| 142 | fi |
| 143 | } |
| 144 | |
| 145 | function print_selection { |
| 146 | echo -e "$1" | $(read -r -d '' entry; echo "echo $entry") |
| 147 | } |
| 148 | |
| 149 | declare -A messages |
| 150 | declare -A confirmationMessages |
| 151 | for entry in "${all[@]}" |
| 152 | do |
| 153 | messages[$entry]=$(write_message "${icons[$entry]}" "${texts[$entry]^}") |
| 154 | done |
| 155 | for entry in "${all[@]}" |
| 156 | do |
| 157 | confirmationMessages[$entry]=$(write_message "${icons[$entry]}" "Yes, ${texts[$entry]}") |
| 158 | done |
| 159 | confirmationMessages[cancel]=$(write_message "${icons[cancel]}" "No, cancel") |
| 160 | |
| 161 | if [ $# -gt 0 ] |
| 162 | then |
| 163 | selection="${@}" |
| 164 | else |
| 165 | if [ -n "${selectionID+x}" ] |
| 166 | then |
| 167 | selection="${messages[$selectionID]}" |
| 168 | fi |
| 169 | fi |
| 170 | |
| 171 | echo -e "\0no-custom\x1ftrue" |
| 172 | echo -e "\0markup-rows\x1ftrue" |
| 173 | |
| 174 | if [ -z "${selection+x}" ] |
| 175 | then |
| 176 | echo -e "\0prompt\x1fPower menu" |
| 177 | for entry in "${show[@]}" |
| 178 | do |
| 179 | echo -e "${messages[$entry]}\0icon\x1f${icons[$entry]}" |
| 180 | done |
| 181 | else |
| 182 | for entry in "${show[@]}" |
| 183 | do |
| 184 | if [ "$selection" = "$(print_selection "${messages[$entry]}")" ] |
| 185 | then |
| 186 | for confirmation in "${confirmations[@]}" |
| 187 | do |
| 188 | if [ "$entry" = "$confirmation" ] |
| 189 | then |
| 190 | echo -e "\0prompt\x1fAre you sure" |
| 191 | echo -e "${confirmationMessages[$entry]}\0icon\x1f${icons[$entry]}" |
| 192 | echo -e "${confirmationMessages[cancel]}\0icon\x1f${icons[cancel]}" |
| 193 | exit 0 |
| 194 | fi |
| 195 | done |
| 196 | selection=$(print_selection "${confirmationMessages[$entry]}") |
| 197 | fi |
| 198 | if [ "$selection" = "$(print_selection "${confirmationMessages[$entry]}")" ] |
| 199 | then |
| 200 | if [ $dryrun = true ] |
| 201 | then |
| 202 | echo "Selected: $entry" >&2 |
| 203 | else |
| 204 | ${actions[$entry]} |
| 205 | fi |
| 206 | exit 0 |
| 207 | fi |
| 208 | if [ "$selection" = "$(print_selection "${confirmationMessages[cancel]}")" ] |
| 209 | then |
| 210 | exit 0 |
| 211 | fi |
| 212 | done |
| 213 | echo "Invalid selection: $selection" >&2 |
| 214 | exit 1 |
| 215 | fi |