Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,26 @@ The following example assumes it's in the same folder as your script:
message-info "Hello!"
```

### Re-running Environment Detection

If your script switches contexts (e.g., from CI to interactive mode) or you've forced a specific mode and want to redetect, you can call `detect_environment()`:

```bash
# Force fallback mode for CI
INTERFACE=""
GUI=false

# ... some CI operations ...

# Later, when entering interactive context, re-detect
unset INTERFACE # Clear forced settings
unset GUI
detect_environment # Re-run detection

# Now INTERFACE and GUI are set based on current environment
message-info "Now using ${INTERFACE} interface"
```

## Modular Structure

The library is organized into modular files for easier maintenance and development. When you source `script-dialog.sh`, it automatically loads all required modules:
Expand Down Expand Up @@ -89,6 +109,7 @@ Functions
----------------
| Name | Description | Arguments | Output or Return |
| ---- | ----------- | --------- | ---------------- |
| **detect_environment** | Re-run environment detection to update `INTERFACE`, `GUI`, `DETECTED_DESKTOP`, and related variables. Useful when switching contexts (e.g., from CI to interactive) or after forcing a mode | None | Updates global variables |
| **superuser** | Attempts to run a privileged command (sudo or equivalent) | Command to run with elevated privilege | return code 0 if success, non-zero otherwise |
| **relaunch-if-not-visible** | if neither GUI nor terminal interfaces can be used, relaunch the script in a terminal emulator | | |
| **message-info** | Display an 'info' message box | The text to display | |
Expand Down
286 changes: 156 additions & 130 deletions init.sh
Original file line number Diff line number Diff line change
Expand Up @@ -13,143 +13,169 @@
# Do auto-detections at the top
################################

# Detect desktop environment for optimal dialog selection
# Priority: OS type -> XDG variables -> running processes

if [[ $OSTYPE == darwin* ]]; then
desktop="macos"
elif [[ $OSTYPE == msys ]] || [[ $(uname -r | tr '[:upper:]' '[:lower:]') == *wsl* ]]; then
desktop="windows"
elif [ -n "$XDG_CURRENT_DESKTOP" ]; then
# shellcheck disable=SC2001
desktop=$(echo "$XDG_CURRENT_DESKTOP" | tr '[:upper:]' '[:lower:]' | sed 's/.*\(xfce\|kde\|gnome\).*/\1/')
elif [ -n "$XDG_SESSION_DESKTOP" ]; then
# shellcheck disable=SC2001
desktop=$(echo "$XDG_SESSION_DESKTOP" | tr '[:upper:]' '[:lower:]' | sed 's/.*\(xfce\|kde\|gnome\).*/\1/')
elif command -v >/dev/null pgrep && pgrep -l "gnome-shell" > /dev/null; then
desktop="gnome"
elif command -v >/dev/null pgrep && pgrep -l "mutter" > /dev/null; then
desktop="gnome"
elif command -v >/dev/null pgrep && pgrep -l "kwin" > /dev/null; then
desktop="kde"
else
desktop="unknown"
fi

# Ensure lowercase for consistent comparisons (redundant for some paths above)
desktop=$(echo "$desktop" | tr '[:upper:]' '[:lower:]')
export DETECTED_DESKTOP=$desktop

# If we have a standard in and out, then terminal
[ -t 0 ] && [ -t 1 ] && terminal=true || terminal=false

# Initialize dialog tool availability flags

hasKDialog=false
hasZenity=false
hasDialog=false
hasWhiptail=false

# Determine if GUI is available (unless already set)
if [ -z ${GUI+x} ]; then
GUI=false
if [ "$terminal" == "false" ] ; then
GUI=$([ "$DISPLAY" ] || [ "$WAYLAND_DISPLAY" ] || [ "$MIR_SOCKET" ] && echo true || echo false)
#######################################
# Detect or re-detect the environment and available dialog tools
# This function can be called to re-run environment detection,
# useful when switching contexts (e.g., from CI to interactive)
# GLOBALS:
# DETECTED_DESKTOP - Set to detected desktop environment
# desktop - Internal variable for desktop environment
# terminal - Set to true if running in terminal
# GUI - Set to true if GUI is available (unless pre-set by user)
# INTERFACE - Set to best available dialog interface (unless pre-set by user)
# hasKDialog, hasZenity, hasDialog, hasWhiptail - Set based on available tools
# NO_SUDO, SUDO, SUDO_USE_INTERFACE - Set based on available privilege elevation
# NO_READ_DEFAULT - Set based on read command capabilities
# ZENITY_ICON_ARG - Set based on zenity version
# ARGUMENTS:
# None
# OUTPUTS:
# None
# RETURN:
# 0 always
#######################################
function detect_environment() {
# Detect desktop environment for optimal dialog selection
# Priority: OS type -> XDG variables -> running processes

if [[ $OSTYPE == darwin* ]]; then
desktop="macos"
elif [[ $OSTYPE == msys ]] || [[ $(uname -r | tr '[:upper:]' '[:lower:]') == *wsl* ]]; then
desktop="windows"
elif [ -n "$XDG_CURRENT_DESKTOP" ]; then
# shellcheck disable=SC2001
desktop=$(echo "$XDG_CURRENT_DESKTOP" | tr '[:upper:]' '[:lower:]' | sed 's/.*\(xfce\|kde\|gnome\).*/\1/')
elif [ -n "$XDG_SESSION_DESKTOP" ]; then
# shellcheck disable=SC2001
desktop=$(echo "$XDG_SESSION_DESKTOP" | tr '[:upper:]' '[:lower:]' | sed 's/.*\(xfce\|kde\|gnome\).*/\1/')
elif command -v >/dev/null pgrep && pgrep -l "gnome-shell" > /dev/null; then
desktop="gnome"
elif command -v >/dev/null pgrep && pgrep -l "mutter" > /dev/null; then
desktop="gnome"
elif command -v >/dev/null pgrep && pgrep -l "kwin" > /dev/null; then
desktop="kde"
else
desktop="unknown"
fi
fi

# Check which dialog tools are available

if command -v >/dev/null kdialog; then
hasKDialog=true
fi

if command -v >/dev/null zenity; then
hasZenity=true
fi

if command -v >/dev/null dialog; then
hasDialog=true
fi

if command -v >/dev/null whiptail; then
hasWhiptail=true
fi

# Auto-select the best available dialog interface based on desktop environment
if [ -z ${INTERFACE+x} ]; then
if [ "$desktop" == "kde" ] || [ "$desktop" == "razor" ] || [ "$desktop" == "lxqt" ] || [ "$desktop" == "maui" ] ; then
if [ "$hasKDialog" == "true" ] && [ "$GUI" == "true" ] ; then
INTERFACE="kdialog"
GUI=true
elif [ "$hasZenity" == "true" ] && [ "$GUI" == "true" ] ; then
INTERFACE="zenity"
GUI=true
elif [ "$hasDialog" == "true" ] ; then
INTERFACE="dialog"
GUI=false
elif [ "$hasWhiptail" == "true" ] ; then
INTERFACE="whiptail"
GUI=false

# Ensure lowercase for consistent comparisons (redundant for some paths above)
desktop=$(echo "$desktop" | tr '[:upper:]' '[:lower:]')
export DETECTED_DESKTOP=$desktop

# If we have a standard in and out, then terminal
[ -t 0 ] && [ -t 1 ] && terminal=true || terminal=false

# Initialize dialog tool availability flags

hasKDialog=false
hasZenity=false
hasDialog=false
hasWhiptail=false

# Determine if GUI is available (unless already set)
if [ -z ${GUI+x} ]; then
GUI=false
if [ "$terminal" == "false" ] ; then
GUI=$([ "$DISPLAY" ] || [ "$WAYLAND_DISPLAY" ] || [ "$MIR_SOCKET" ] && echo true || echo false)
fi
elif [ "$desktop" == "unity" ] || [ "$desktop" == "gnome" ] || [ "$desktop" == "xfce" ] || [ -n "$INTERFACE" ]; then
if [ "$hasZenity" == "true" ] && [ "$GUI" == "true" ] ; then
INTERFACE="zenity"
GUI=true
elif [ "$hasDialog" == "true" ] ; then
INTERFACE="dialog"
GUI=false
elif [ "$hasWhiptail" == "true" ] ; then
INTERFACE="whiptail"
GUI=false
fi

# Check which dialog tools are available

if command -v >/dev/null kdialog; then
hasKDialog=true
fi

if command -v >/dev/null zenity; then
hasZenity=true
fi

if command -v >/dev/null dialog; then
hasDialog=true
fi

if command -v >/dev/null whiptail; then
hasWhiptail=true
fi

# Auto-select the best available dialog interface based on desktop environment
if [ -z ${INTERFACE+x} ]; then
if [ "$desktop" == "kde" ] || [ "$desktop" == "razor" ] || [ "$desktop" == "lxqt" ] || [ "$desktop" == "maui" ] ; then
if [ "$hasKDialog" == "true" ] && [ "$GUI" == "true" ] ; then
INTERFACE="kdialog"
GUI=true
elif [ "$hasZenity" == "true" ] && [ "$GUI" == "true" ] ; then
INTERFACE="zenity"
GUI=true
elif [ "$hasDialog" == "true" ] ; then
INTERFACE="dialog"
GUI=false
elif [ "$hasWhiptail" == "true" ] ; then
INTERFACE="whiptail"
GUI=false
fi
elif [ "$desktop" == "unity" ] || [ "$desktop" == "gnome" ] || [ "$desktop" == "xfce" ] || [ -n "$INTERFACE" ]; then
if [ "$hasZenity" == "true" ] && [ "$GUI" == "true" ] ; then
INTERFACE="zenity"
GUI=true
elif [ "$hasDialog" == "true" ] ; then
INTERFACE="dialog"
GUI=false
elif [ "$hasWhiptail" == "true" ] ; then
INTERFACE="whiptail"
GUI=false
fi
else
if [ "$hasDialog" == "true" ] ; then
INTERFACE="dialog"
GUI=false
elif [ "$hasWhiptail" == "true" ] ; then
INTERFACE="whiptail"
GUI=false
fi
fi
else
if [ "$hasDialog" == "true" ] ; then
INTERFACE="dialog"
GUI=false
elif [ "$hasWhiptail" == "true" ] ; then
INTERFACE="whiptail"
GUI=false
fi

# Handle Zenity major version difference
ZENITY_ICON_ARG=--icon
if command -v >/dev/null zenity && printf "%s\n4.0.0\n" "$(zenity --version)" | sort -C; then
# this version is older than 4.0.0
ZENITY_ICON_ARG=--icon-name
fi

if [ "$INTERFACE" == "kdialog" ] || [ "$INTERFACE" == "zenity" ] ; then
GUI=true
fi

# Select the best available sudo/privilege elevation method
NO_SUDO=false
SUDO_USE_INTERFACE=false
if [ "$GUI" == "true" ] && command -v >/dev/null pkexec; then
SUDO="pkexec env DISPLAY=$DISPLAY XAUTHORITY=$XAUTHORITY"
elif [ "$INTERFACE" == "kdialog" ] && command -v >/dev/null gksudo; then
SUDO="kdesudo"
elif [ "$GUI" == "true" ] && command -v >/dev/null gksudo; then
SUDO="gksudo"
elif [ "$GUI" == "true" ] && command -v >/dev/null gksu; then
SUDO="gksu"
elif command -v >/dev/null sudo; then
SUDO="sudo"
if [ "$INTERFACE" == "whiptail" ] || [ "$INTERFACE" == "dialog" ]; then
SUDO_USE_INTERFACE=true
fi
else
NO_SUDO=true
fi
fi

# Handle Zenity major version difference
ZENITY_ICON_ARG=--icon
if command -v >/dev/null zenity && printf "%s\n4.0.0\n" "$(zenity --version)" | sort -C; then
# this version is older than 4.0.0
ZENITY_ICON_ARG=--icon-name
fi

if [ "$INTERFACE" == "kdialog" ] || [ "$INTERFACE" == "zenity" ] ; then
GUI=true
fi

# Select the best available sudo/privilege elevation method
NO_SUDO=false
SUDO_USE_INTERFACE=false
if [ "$GUI" == "true" ] && command -v >/dev/null pkexec; then
SUDO="pkexec env DISPLAY=$DISPLAY XAUTHORITY=$XAUTHORITY"
elif [ "$INTERFACE" == "kdialog" ] && command -v >/dev/null gksudo; then
SUDO="kdesudo"
elif [ "$GUI" == "true" ] && command -v >/dev/null gksudo; then
SUDO="gksudo"
elif [ "$GUI" == "true" ] && command -v >/dev/null gksu; then
SUDO="gksu"
elif command -v >/dev/null sudo; then
SUDO="sudo"
if [ "$INTERFACE" == "whiptail" ] || [ "$INTERFACE" == "dialog" ]; then
SUDO_USE_INTERFACE=true

# Handle when read command doesn't support default text option
NO_READ_DEFAULT="-r"
if echo "test" | read -ri "test" 2>/dev/null; then
NO_READ_DEFAULT=""
fi
else
NO_SUDO=true
fi
}

# Handle when read command doesn't support default text option
NO_READ_DEFAULT="-r"
if echo "test" | read -ri "test" 2>/dev/null; then
NO_READ_DEFAULT=""
fi
# Run initial environment detection
detect_environment

# Set default cancel exit code if not already set
if [ -z "${SCRIPT_DIALOG_CANCEL_EXIT_CODE+x}" ]; then
Expand Down