shutdown_menu 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. #!/usr/bin/env bash
  2. #
  3. # Use rofi/zenity to change system runstate thanks to systemd.
  4. #
  5. # Note: this currently relies on associative array support in the shell.
  6. #
  7. # Inspired from i3pystatus wiki:
  8. # https://github.com/enkore/i3pystatus/wiki/Shutdown-Menu
  9. #
  10. # Copyright 2015 Benjamin Chrétien <chretien at lirmm dot fr>
  11. #
  12. # This program is free software: you can redistribute it and/or modify
  13. # it under the terms of the GNU General Public License as published by
  14. # the Free Software Foundation, either version 3 of the License, or
  15. # (at your option) any later version.
  16. # This program is distributed in the hope that it will be useful,
  17. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  19. # GNU General Public License for more details.
  20. # You should have received a copy of the GNU General Public License
  21. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  22. #######################################################################
  23. # BEGIN CONFIG #
  24. #######################################################################
  25. # Use a custom lock script
  26. LOCKSCRIPT="sh Dokumente/scripts/lock.sh"
  27. # Colors: FG (foreground), BG (background), HL (highlighted)
  28. FG_COLOR="#bbbbbb"
  29. BG_COLOR="#111111"
  30. HLFG_COLOR="#111111"
  31. HLBG_COLOR="#bbbbbb"
  32. BORDER_COLOR="#222222"
  33. # Options not related to colors
  34. ROFI_TEXT="Menu:"
  35. ROFI_OPTIONS=(-width -11 -location 3 -hide-scrollbar -bw 2)
  36. # Zenity options
  37. ZENITY_TITLE="Menu"
  38. ZENITY_TEXT="Action:"
  39. ZENITY_OPTIONS=(--column= --hide-header)
  40. #######################################################################
  41. # END CONFIG #
  42. #######################################################################
  43. # Whether to ask for user's confirmation
  44. enable_confirmation=false
  45. # Preferred launcher if both are available
  46. preferred_launcher="rofi"
  47. usage="$(basename "$0") [-h] [-c] [-p name] -- display a menu for shutdown, reboot, lock etc.
  48. where:
  49. -h show this help text
  50. -c ask for user confirmation
  51. -p preferred launcher (rofi or zenity)
  52. This script depends on:
  53. - systemd,
  54. - i3,
  55. - rofi or zenity."
  56. # Check whether the user-defined launcher is valid
  57. launcher_list=(rofi zenity)
  58. function check_launcher() {
  59. if [[ ! "${launcher_list[@]}" =~ (^|[[:space:]])"$1"($|[[:space:]]) ]]; then
  60. echo "Supported launchers: ${launcher_list[*]}"
  61. exit 1
  62. else
  63. # Get array with unique elements and preferred launcher first
  64. # Note: uniq expects a sorted list, so we cannot use it
  65. i=1
  66. launcher_list=($(for l in "$1" "${launcher_list[@]}"; do printf "%i %s\n" "$i" "$l"; let i+=1; done \
  67. | sort -uk2 | sort -nk1 | cut -d' ' -f2- | tr '\n' ' '))
  68. fi
  69. }
  70. # Parse CLI arguments
  71. while getopts "hcp:" option; do
  72. case "${option}" in
  73. h) echo "${usage}"
  74. exit 0
  75. ;;
  76. c) enable_confirmation=true
  77. ;;
  78. p) preferred_launcher="${OPTARG}"
  79. check_launcher "${preferred_launcher}"
  80. ;;
  81. *) exit 1
  82. ;;
  83. esac
  84. done
  85. # Check whether a command exists
  86. function command_exists() {
  87. command -v "$1" &> /dev/null 2>&1
  88. }
  89. # systemctl required
  90. if ! command_exists systemctl ; then
  91. exit 1
  92. fi
  93. # menu defined as an associative array
  94. typeset -A menu
  95. # Menu with keys/commands
  96. menu=(
  97. [Shutdown]="systemctl poweroff"
  98. [Reboot]="systemctl reboot"
  99. [Hibernate]="systemctl hibernate"
  100. [Suspend]="systemctl suspend"
  101. [Halt]="systemctl halt"
  102. [Lock]="${LOCKSCRIPT:-i3lock --color=${BG_COLOR#"#"}}"
  103. [Logout]="i3-msg exit"
  104. [Cancel]=""
  105. )
  106. menu_nrows=${#menu[@]}
  107. # Menu entries that may trigger a confirmation message
  108. menu_confirm="Shutdown Reboot Hibernate Suspend Halt Logout"
  109. launcher_exe=""
  110. launcher_options=""
  111. rofi_colors=""
  112. function prepare_launcher() {
  113. if [[ "$1" == "rofi" ]]; then
  114. rofi_colors=(-bc "${BORDER_COLOR}" -bg "${BG_COLOR}" -fg "${FG_COLOR}" \
  115. -hlfg "${HLFG_COLOR}" -hlbg "${HLBG_COLOR}")
  116. launcher_exe="rofi"
  117. launcher_options=(-dmenu -i -lines "${menu_nrows}" -p "${ROFI_TEXT}" \
  118. "${rofi_colors}" "${ROFI_OPTIONS[@]}")
  119. elif [[ "$1" == "zenity" ]]; then
  120. launcher_exe="zenity"
  121. launcher_options=(--list --title="${ZENITY_TITLE}" --text="${ZENITY_TEXT}" \
  122. "${ZENITY_OPTIONS[@]}")
  123. fi
  124. }
  125. for l in "${launcher_list[@]}"; do
  126. if command_exists "${l}" ; then
  127. prepare_launcher "${l}"
  128. break
  129. fi
  130. done
  131. # No launcher available
  132. if [[ -z "${launcher_exe}" ]]; then
  133. exit 1
  134. fi
  135. launcher=(${launcher_exe} "${launcher_options[@]}")
  136. selection="$(printf '%s\n' "${!menu[@]}" | sort | "${launcher[@]}")"
  137. function ask_confirmation() {
  138. if [ "${launcher_exe}" == "rofi" ]; then
  139. confirmed=$(echo -e "Yes\nNo" | rofi -dmenu -i -lines 2 -p "${selection}?" \
  140. "${rofi_colors}" "${ROFI_OPTIONS[@]}")
  141. [ "${confirmed}" == "Yes" ] && confirmed=0
  142. elif [ "${launcher_exe}" == "zenity" ]; then
  143. zenity --question --text "Are you sure you want to ${selection,,}?"
  144. confirmed=$?
  145. fi
  146. if [ "${confirmed}" == 0 ]; then
  147. i3-msg -q "exec ${menu[${selection}]}"
  148. fi
  149. }
  150. if [[ $? -eq 0 && ! -z ${selection} ]]; then
  151. if [[ "${enable_confirmation}" = true && \
  152. ${menu_confirm} =~ (^|[[:space:]])"${selection}"($|[[:space:]]) ]]; then
  153. ask_confirmation
  154. else
  155. i3-msg -q "exec ${menu[${selection}]}"
  156. fi
  157. fi