Fixed some shellcheck errors. Added the ability to save answers to i38 questions thereby making future configuration regeneration much easier.
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,3 +1,4 @@
|
||||
I38_preferences.conf
|
||||
**/__pycache__/
|
||||
*.pyc
|
||||
*.pyo
|
||||
|
||||
388
i38.sh
388
i38.sh
@@ -15,6 +15,7 @@
|
||||
usingSway=1 # Not by default.
|
||||
i3Path="${XDG_CONFIG_HOME:-$HOME/.config}/i3"
|
||||
i3msg="i3-msg"
|
||||
configFile="${PWD}/I38_preferences.conf"
|
||||
|
||||
# Dialog accessibility
|
||||
export DIALOGOPTS='--no-lines --visit-items'
|
||||
@@ -28,7 +29,7 @@ done
|
||||
if ! python3 -c 'import i3ipc' &> /dev/null ; then
|
||||
missing+=("python-i3ipc")
|
||||
fi
|
||||
if [[ -n "${missing}" ]]; then
|
||||
if [[ ${#missing[@]} -gt 0 ]]; then
|
||||
echo "Please install the following packages and run this script again:"
|
||||
echo "${missing[*]}"
|
||||
exit 1
|
||||
@@ -175,7 +176,7 @@ yesno() {
|
||||
# Returns: Yes 0 or No 1
|
||||
# Args: Question to user.
|
||||
dialog --clear --title "I38" --yesno "$*" -1 -1 --stdout
|
||||
echo $?
|
||||
return $?
|
||||
}
|
||||
|
||||
# Custom application keybinding functions
|
||||
@@ -333,7 +334,80 @@ addCustomApplication() {
|
||||
break
|
||||
done
|
||||
done
|
||||
}
|
||||
}
|
||||
|
||||
load_config() {
|
||||
# Load existing configuration if available
|
||||
if [[ -f "$configFile" ]]; then
|
||||
# shellcheck source=/dev/null
|
||||
source "$configFile"
|
||||
|
||||
# Convert kbd string back to array if present
|
||||
if [[ -n "$kbd" ]]; then
|
||||
IFS=' ' read -ra kbd <<< "$kbd"
|
||||
fi
|
||||
|
||||
# Reconstruct customApps array from numbered entries
|
||||
customApps=()
|
||||
local i=0
|
||||
local varName
|
||||
while : ; do
|
||||
varName="customApp_$i"
|
||||
if [[ -n "${!varName}" ]]; then
|
||||
customApps+=("${!varName}")
|
||||
((i++))
|
||||
else
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
return 0
|
||||
fi
|
||||
return 1
|
||||
}
|
||||
|
||||
save_config() {
|
||||
if yesno "Save this configuration for future runs?"; then
|
||||
cat > "$configFile" << EOF
|
||||
# I38 Configuration Preferences
|
||||
# Generated by i38.sh on $(date)
|
||||
# Edit this file to change saved preferences or delete to reconfigure from scratch
|
||||
|
||||
# Keyboard configuration
|
||||
escapeKey="$escapeKey"
|
||||
mod="$mod"
|
||||
|
||||
# Keyboard layouts (space-separated)
|
||||
kbd="${kbd[*]}"
|
||||
|
||||
# Volume settings
|
||||
volumeJump="$volumeJump"
|
||||
|
||||
# Application paths
|
||||
screenReader="$screenReader"
|
||||
emailClient="$emailClient"
|
||||
webBrowser="$webBrowser"
|
||||
textEditor="$textEditor"
|
||||
fileBrowser="$fileBrowser"
|
||||
ircClient="$ircClient"
|
||||
|
||||
# Boolean settings (0=yes, 1=no)
|
||||
udiskie="$udiskie"
|
||||
dex="$dex"
|
||||
batteryAlert="${batteryAlert:-1}"
|
||||
brlapi="$brlapi"
|
||||
sounds="$sounds"
|
||||
|
||||
# Custom applications
|
||||
EOF
|
||||
# Save custom apps with numbered keys
|
||||
for i in "${!customApps[@]}"; do
|
||||
echo "customApp_$i=\"${customApps[$i]}\"" >> "$configFile"
|
||||
done
|
||||
|
||||
dialog --title "I38" --msgbox "Configuration saved to $configFile\n\nYou can edit this file manually or delete it to reconfigure from scratch." 0 0
|
||||
fi
|
||||
}
|
||||
|
||||
help() {
|
||||
echo "${0##*/}"
|
||||
@@ -344,6 +418,9 @@ help() {
|
||||
for i in "${!command[@]}" ; do
|
||||
echo "-${i/:/ <parameter>}: ${command[${i}]}"
|
||||
done | sort
|
||||
echo ""
|
||||
echo "Configuration preferences can be saved to I38_preferences.conf in the current directory."
|
||||
echo "Delete this file to reconfigure from scratch."
|
||||
exit 0
|
||||
}
|
||||
|
||||
@@ -378,8 +455,7 @@ chmod +x ~/.xinitrc
|
||||
|
||||
write_xprofile() {
|
||||
if [[ -f "$HOME/.xprofile" ]]; then
|
||||
continue="$(yesno "Would you like to add accessibility variables to your $HOME/.xprofile? Without these, accessibility will be limited or may not work at all. Do you want to continue?")"
|
||||
if [ "$continue" = "no" ]; then
|
||||
if ! yesno "Would you like to add accessibility variables to your $HOME/.xprofile? Without these, accessibility will be limited or may not work at all. Do you want to continue?"; then
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
@@ -467,6 +543,13 @@ while getopts "${args}" i ; do
|
||||
esac
|
||||
done
|
||||
|
||||
# Load saved configuration if available
|
||||
configLoaded=0
|
||||
if load_config; then
|
||||
configLoaded=1
|
||||
dialog --title "I38" --msgbox "Loaded saved preferences from $configFile\n\nMissing or invalid values will be prompted." 0 0
|
||||
fi
|
||||
|
||||
# Mod1 alt
|
||||
# Mod4 super
|
||||
# Mod2 and Mod3 not usually defined.
|
||||
@@ -475,155 +558,224 @@ done
|
||||
# Ratpoison mode is enabled by default
|
||||
export i3Mode=0
|
||||
# Prevent setting ratpoison mode key to the same as default mode key
|
||||
while [[ "$escapeKey" == "$mod" ]] || [[ "$escapeKey" =~ ^Super_ && "$mod" == "Mod4" ]] || [[ "$mod" == "Mod4" && "$escapeKey" =~ ^Super_ ]]; do
|
||||
escapeKey="$(menulist "Ratpoison mode key:" Control+t Control+z Control+Escape Alt+Escape Control+space "Super Left" "Super Right")"
|
||||
escapeKey="${escapeKey//Alt/Mod1}"
|
||||
escapeKey="${escapeKey//Super Left/Super_L}"
|
||||
escapeKey="${escapeKey//Super Right/Super_R}"
|
||||
mod="$(menulist "I3 mod key, for top level bindings:" Alt Super)"
|
||||
mod="${mod//Alt/Mod1}"
|
||||
mod="${mod//Super/Mod4}"
|
||||
if [ "$escapeKey" == "$mod" ]; then
|
||||
dialog --title "I38" --msgbox "Ratpoison and mod key cannot be the same key." -1 -1
|
||||
elif [[ "$escapeKey" =~ ^Super_ && "$mod" == "Mod4" ]]; then
|
||||
dialog --title "I38" --msgbox "Ratpoison mode key cannot be a Super key when mod key is Super." -1 -1
|
||||
fi
|
||||
done
|
||||
# Multiple keyboard layouts
|
||||
if [[ $(yesno "Do you want to use multiple keyboard layouts?") -eq 0 ]]; then
|
||||
unset kbd
|
||||
while : ; do
|
||||
kbd+=("$(keyboard_menu)") || break
|
||||
if [[ -z "$escapeKey" ]] || [[ -z "$mod" ]]; then
|
||||
while [[ "$escapeKey" == "$mod" ]] || [[ "$escapeKey" =~ ^Super_ && "$mod" == "Mod4" ]] || [[ "$mod" == "Mod4" && "$escapeKey" =~ ^Super_ ]]; do
|
||||
escapeKey="$(menulist "Ratpoison mode key:" Control+t Control+z Control+Escape Alt+Escape Control+space "Super Left" "Super Right")"
|
||||
escapeKey="${escapeKey//Alt/Mod1}"
|
||||
escapeKey="${escapeKey//Super Left/Super_L}"
|
||||
escapeKey="${escapeKey//Super Right/Super_R}"
|
||||
mod="$(menulist "I3 mod key, for top level bindings:" Alt Super)"
|
||||
mod="${mod//Alt/Mod1}"
|
||||
mod="${mod//Super/Mod4}"
|
||||
if [ "$escapeKey" == "$mod" ]; then
|
||||
dialog --title "I38" --msgbox "Ratpoison and mod key cannot be the same key." -1 -1
|
||||
elif [[ "$escapeKey" =~ ^Super_ && "$mod" == "Mod4" ]]; then
|
||||
dialog --title "I38" --msgbox "Ratpoison mode key cannot be a Super key when mod key is Super." -1 -1
|
||||
fi
|
||||
done
|
||||
fi
|
||||
# Multiple keyboard layouts
|
||||
if [[ ${#kbd[@]} -eq 0 ]]; then
|
||||
if yesno "Do you want to use multiple keyboard layouts?"; then
|
||||
unset kbd
|
||||
while : ; do
|
||||
kbd+=("$(keyboard_menu)") || break
|
||||
done
|
||||
fi
|
||||
fi
|
||||
# Volume jump
|
||||
volumeJump=$(rangebox "How much should pressing the volume keys change the volume?" 1 15 5)
|
||||
if [[ -z "$volumeJump" ]]; then
|
||||
volumeJump=$(rangebox "How much should pressing the volume keys change the volume?" 1 15 5)
|
||||
fi
|
||||
# Screen Reader
|
||||
unset programList
|
||||
for i in cthulhu orca ; do
|
||||
if command -v ${i/#-/} &> /dev/null ; then
|
||||
if [ -n "$programList" ]; then
|
||||
programList="$programList $i"
|
||||
else
|
||||
programList="$i"
|
||||
if [[ -z "$screenReader" ]] || ! command -v "$screenReader" &> /dev/null; then
|
||||
unset programList
|
||||
for i in cthulhu orca ; do
|
||||
if command -v ${i/#-/} &> /dev/null ; then
|
||||
if [ -n "$programList" ]; then
|
||||
programList="$programList $i"
|
||||
else
|
||||
programList="$i"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
if [ "$programList" != "${programList// /}" ]; then
|
||||
screenReader="$(menulist ":Screen Reader" $programList)"
|
||||
else
|
||||
screenReader="${programList/#-/}"
|
||||
fi
|
||||
done
|
||||
if [ "$programList" != "${programList// /}" ]; then
|
||||
screenReader="$(menulist ":Screen Reader" $programList)"
|
||||
export screenReader="$(command -v $screenReader)"
|
||||
else
|
||||
screenReader="${programList/#-/}"
|
||||
# Validate and export existing preference
|
||||
export screenReader
|
||||
fi
|
||||
export screenReader="$(command -v $screenReader)"
|
||||
# Email client
|
||||
unset programList
|
||||
for i in betterbird evolution thunderbird ; do
|
||||
if command -v ${i/#-/} &> /dev/null ; then
|
||||
if [ -n "$programList" ]; then
|
||||
programList="$programList $i"
|
||||
else
|
||||
programList="$i"
|
||||
if [[ -z "$emailClient" ]] || ! command -v "$emailClient" &> /dev/null; then
|
||||
unset programList
|
||||
for i in betterbird evolution thunderbird ; do
|
||||
if command -v ${i/#-/} &> /dev/null ; then
|
||||
if [ -n "$programList" ]; then
|
||||
programList="$programList $i"
|
||||
else
|
||||
programList="$i"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
if [ "$programList" != "${programList// /}" ]; then
|
||||
emailClient="$(menulist "Email client:" $programList)"
|
||||
else
|
||||
emailClient="${programList/#-/}"
|
||||
fi
|
||||
done
|
||||
if [ "$programList" != "${programList// /}" ]; then
|
||||
emailClient="$(menulist "Email client:" $programList)"
|
||||
export emailClient="$(command -v $emailClient)"
|
||||
else
|
||||
emailClient="${programList/#-/}"
|
||||
# Validate and export existing preference
|
||||
export emailClient
|
||||
fi
|
||||
export emailClient="$(command -v $emailClient)"
|
||||
# Web browser
|
||||
unset programList
|
||||
for i in brave chromium epiphany firefox google-chrome-stable google-chrome-unstable microsoft-edge-stable microsoft-edge-beta microsoft-edge-dev midori seamonkey vivaldi ; do
|
||||
if command -v ${i/#-/} &> /dev/null ; then
|
||||
if [ -n "$programList" ]; then
|
||||
programList="$programList $i"
|
||||
else
|
||||
programList="$i"
|
||||
if [[ -z "$webBrowser" ]] || ! command -v "$webBrowser" &> /dev/null; then
|
||||
unset programList
|
||||
for i in brave chromium epiphany firefox google-chrome-stable google-chrome-unstable microsoft-edge-stable microsoft-edge-beta microsoft-edge-dev midori seamonkey vivaldi ; do
|
||||
if command -v ${i/#-/} &> /dev/null ; then
|
||||
if [ -n "$programList" ]; then
|
||||
programList="$programList $i"
|
||||
else
|
||||
programList="$i"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
if [ "$programList" != "${programList// /}" ]; then
|
||||
webBrowser="$(menulist "Web browser:" $programList)"
|
||||
else
|
||||
webBrowser="${programList/#-/}"
|
||||
fi
|
||||
done
|
||||
if [ "$programList" != "${programList// /}" ]; then
|
||||
webBrowser="$(menulist "Web browser:" $programList)"
|
||||
export webBrowser="$(command -v $webBrowser)"
|
||||
else
|
||||
webBrowser="${programList/#-/}"
|
||||
# Validate and export existing preference
|
||||
export webBrowser
|
||||
fi
|
||||
export webBrowser="$(command -v $webBrowser)"
|
||||
# Text editor
|
||||
unset programList
|
||||
for i in emacs geany gedit kate kwrite l3afpad leafpad libreoffice mousepad pluma ; do
|
||||
if hash ${i/#-/} &> /dev/null ; then
|
||||
if [ -n "$programList" ]; then
|
||||
programList="$programList $i"
|
||||
if [[ -z "$textEditor" ]] || ! command -v "$textEditor" &> /dev/null; then
|
||||
unset programList
|
||||
for i in emacs geany gedit kate kwrite l3afpad leafpad libreoffice mousepad pluma ; do
|
||||
if hash ${i/#-/} &> /dev/null ; then
|
||||
if [ -n "$programList" ]; then
|
||||
programList="$programList $i"
|
||||
else
|
||||
programList="$i"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
if [ "$programList" != "${programList// /}" ]; then
|
||||
textEditor="$(menulist "Text editor:" $programList)"
|
||||
else
|
||||
textEditor="${programList/#-/}"
|
||||
fi
|
||||
export textEditor="$(command -v $textEditor)"
|
||||
else
|
||||
programList="$i"
|
||||
# Validate and export existing preference
|
||||
export textEditor
|
||||
fi
|
||||
fi
|
||||
done
|
||||
if [ "$programList" != "${programList// /}" ]; then
|
||||
textEditor="$(menulist "Text editor:" $programList)"
|
||||
else
|
||||
textEditor="${programList/#-/}"
|
||||
fi
|
||||
export textEditor="$(command -v $textEditor)"
|
||||
# File browser
|
||||
# Configure file browser
|
||||
unset programList
|
||||
for i in caja nemo nautilus pcmanfm pcmanfm-qt thunar ; do
|
||||
if hash ${i/#-/} &> /dev/null ; then
|
||||
if [ -n "$programList" ]; then
|
||||
programList="$programList $i"
|
||||
else
|
||||
programList="$i"
|
||||
if [[ -z "$fileBrowser" ]] || ! command -v "$fileBrowser" &> /dev/null; then
|
||||
unset programList
|
||||
for i in caja nemo nautilus pcmanfm pcmanfm-qt thunar ; do
|
||||
if hash ${i/#-/} &> /dev/null ; then
|
||||
if [ -n "$programList" ]; then
|
||||
programList="$programList $i"
|
||||
else
|
||||
programList="$i"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
if [ "$programList" != "${programList// /}" ]; then
|
||||
fileBrowser="$(menulist "File browser:" $programList)"
|
||||
else
|
||||
fileBrowser="${programList/#-/}"
|
||||
fi
|
||||
done
|
||||
if [ "$programList" != "${programList// /}" ]; then
|
||||
fileBrowser="$(menulist "File browser:" $programList)"
|
||||
export fileBrowser="$(command -v $fileBrowser)"
|
||||
else
|
||||
fileBrowser="${programList/#-/}"
|
||||
# Validate and export existing preference
|
||||
export fileBrowser
|
||||
fi
|
||||
export fileBrowser="$(command -v $fileBrowser)"
|
||||
# IRC client
|
||||
unset programList
|
||||
for i in albikirc Albikirc access-irc ; do
|
||||
if command -v ${i/#-/} &> /dev/null ; then
|
||||
if [ -n "$programList" ]; then
|
||||
programList="$programList $i"
|
||||
if [[ -z "$ircClient" ]] || ! command -v "$ircClient" &> /dev/null; then
|
||||
unset programList
|
||||
for i in albikirc Albikirc access-irc ; do
|
||||
if command -v ${i/#-/} &> /dev/null ; then
|
||||
if [ -n "$programList" ]; then
|
||||
programList="$programList $i"
|
||||
else
|
||||
programList="$i"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
if [ "$programList" != "${programList// /}" ]; then
|
||||
ircClient="$(menulist "IRC client:" $programList)"
|
||||
else
|
||||
ircClient="${programList/#-/}"
|
||||
fi
|
||||
export ircClient="$(command -v $ircClient)"
|
||||
else
|
||||
# Validate and export existing preference
|
||||
export ircClient
|
||||
fi
|
||||
# Auto mount removable media
|
||||
if [[ -z "$udiskie" ]]; then
|
||||
udiskie=1
|
||||
if command -v udiskie &> /dev/null ; then
|
||||
if yesno "Would you like removable drives to automatically mount when plugged in?"; then
|
||||
export udiskie=0
|
||||
else
|
||||
programList="$i"
|
||||
export udiskie=1
|
||||
fi
|
||||
fi
|
||||
done
|
||||
if [ "$programList" != "${programList// /}" ]; then
|
||||
ircClient="$(menulist "IRC client:" $programList)"
|
||||
else
|
||||
ircClient="${programList/#-/}"
|
||||
fi
|
||||
export ircClient="$(command -v $ircClient)"
|
||||
# Auto mount removable media
|
||||
udiskie=1
|
||||
if command -v udiskie &> /dev/null ; then
|
||||
export udiskie=$(yesno "Would you like removable drives to automatically mount when plugged in?")
|
||||
fi
|
||||
# Auto start with dex
|
||||
dex=1
|
||||
if command -v dex &> /dev/null ; then
|
||||
export dex=$(yesno "Would you like to autostart applications with dex?")
|
||||
if [[ -z "$dex" ]]; then
|
||||
dex=1
|
||||
if command -v dex &> /dev/null ; then
|
||||
if yesno "Would you like to autostart applications with dex?"; then
|
||||
export dex=0
|
||||
else
|
||||
export dex=1
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
if [[ $dex -eq 0 ]]; then
|
||||
dex -t "${XDG_CONFIG_HOME:-${HOME}/.config}/autostart" -c $(command -v $screenReader)
|
||||
fi
|
||||
if command -v acpi &> /dev/null ; then
|
||||
batteryAlert=1
|
||||
batteryAlert=$(yesno "Do you want low battery notifications?")
|
||||
if [[ -z "$batteryAlert" ]]; then
|
||||
if command -v acpi &> /dev/null ; then
|
||||
if yesno "Do you want low battery notifications?"; then
|
||||
batteryAlert=0
|
||||
else
|
||||
batteryAlert=1
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
if [[ -z "$brlapi" ]]; then
|
||||
if yesno "Do you want to use a braille display with ${screenReader##*/}?"; then
|
||||
brlapi=0
|
||||
else
|
||||
brlapi=1
|
||||
fi
|
||||
fi
|
||||
if [[ -z "$sounds" ]]; then
|
||||
if yesno "Do you want window event sounds?"; then
|
||||
sounds=0
|
||||
else
|
||||
sounds=1
|
||||
fi
|
||||
fi
|
||||
brlapi=1
|
||||
brlapi=$(yesno "Do you want to use a braille display with ${screenReader##*/}?")
|
||||
sounds=1
|
||||
sounds=$(yesno "Do you want window event sounds?")
|
||||
# Custom applications for ratpoison mode
|
||||
addCustomApplication
|
||||
if [[ ${#customApps[@]} -eq 0 ]]; then
|
||||
addCustomApplication
|
||||
fi
|
||||
|
||||
# Save configuration if requested (only on first run)
|
||||
if [[ $configLoaded -eq 0 ]]; then
|
||||
save_config
|
||||
fi
|
||||
|
||||
if [[ -d "${i3Path}" ]]; then
|
||||
yesno "This will replace your existing configuration at ${i3Path}. Do you want to continue?" || exit 0
|
||||
@@ -823,7 +975,7 @@ echo "bindsym ${mod}+Shift+F5 exec spd-say -C" >> ${i3Path}/config
|
||||
|
||||
# Multiple keyboard layouts if requested.
|
||||
if [[ ${#kbd[@]} -gt 1 ]]; then
|
||||
echo "bindsym Mod4+space exec ${i3Path}/scripts/keyboard.sh cycle ${kbd[@]}" >> ${i3Path}/config
|
||||
echo "bindsym Mod4+space exec ${i3Path}/scripts/keyboard.sh cycle ${kbd[*]}" >> ${i3Path}/config
|
||||
fi
|
||||
|
||||
# Create panel mode
|
||||
@@ -887,7 +1039,7 @@ mode "ratpoison" {
|
||||
# Ratpoison mode keybindings help bound to F1
|
||||
bindsym F1 exec ${i3Path}/scripts/i38-help-rp.sh, mode "default"
|
||||
# Terminal emulator bound to c
|
||||
bindsym c exec $sensibleTerminal, mode "default"
|
||||
bindsym c exec ${i3Path}/scripts/i3-sensible-terminal.sh, mode "default"
|
||||
# Text editor bound to e
|
||||
bindsym e exec $textEditor, mode "default"
|
||||
$(if [[ ${#fileBrowser} -gt 3 ]]; then
|
||||
|
||||
Reference in New Issue
Block a user