summaryrefslogtreecommitdiff
path: root/scripts/slib
blob: 0e0de36943f24888473580fc562a250fe1473950 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
#!/bin/sh

# Avoid using full paths instead only use the program names.
argv0="${0}"

# @FUNCTION: err
# @USAGE: [-x] <message> ...
# @DESCRIPTION:
# Print given messages to stderr line by line and exit with status 1.
#
# If "-x" is specified, suppress the program prefix (`program: `)
# from the output. Otherwise, the first line is prefixed with "program: ".
#
# This function is intended for fatal errors; it always exits the script.
# @EXAMPLE:
# err "Invalid usage" "Try '${argv0} -h' for help."

err() {
	if [ "${1}" != "-x" ]; then
		printf "%s: " "${argv0}"
	else
		shift
	fi

	for line in "${@}"; do
		echo "${line}" >&2
	done
	exit 1
}

# @FUNCTION: invalid_use
# USAGE: [-h]
# @DESCRIPTION:
# Output a usage error message. If `-h` is not specified output:
# 	"<program>: Invalid usage "
# 	"Try 'program -h' for help."
# else output only:
# 	"Try 'program -h' for help."

invalid_use() {
	[ "${1}" = "-h" ] && err -x "Try '${argv0} -h' for help."
	err "Invalid usage" "Try '${argv0} -h' for help."
}

# @FUNCTION: check_program
# USAGE: <command> [error-msg]
# @DESCRIPTION:
# Check if command exists on the system.
# If not, print an error message to stderr and exit with status 1.
# The default error message is "`command` must be installed"
# but can optionally be overwritten.
#
# @EXAMPLE:
# Check if pulseaudio is installed.
#
# check_program "pactl" "pulseaudio must be installed"

check_program() {
	command -v "${1}" > /dev/null 2>&1 && return 0
	[ -n "${2}" ] && err "${2}"
	err "${1} must be installed"
}

# @FUNCTION: run
# @USAGE: [--reload-status] [--reload-compositor] [--on-success <cmd>] [--on-failure <cmd>] <command> [success-msg] [failure-msg]
# @DESCRIPTION:
# Safely execute a simple shell command, print optional success/failure messages,
# and optionally reload status bars or restart the compositor.
#
# Success messages are printed to stdout; failure messages are printed to stderr.
# To specify a failure message, a success message must also be provided.
# Command output is not suppressed.
#
# Options:
#   --reload-status        Reload the status bar (via `slreload`).
#   --reload-compositor    Restart the compositor (kills and restarts `picom`).
#   --on-success <cmd>     Run another command if the main command succeeds.
#   --on-failure <cmd>     Run another command if the main command fails.
#
# Restrictions:
#   - Does NOT use `eval`; only simple commands and arguments are supported.
#   - Shell operators like `&&`, `||`, `|`, `>`, `>>`, etc. will NOT work.
#   - This design prevents unintended execution and makes the function safe in scripts.
#
# Return value:
#   0 if the command succeeds, 1 otherwise.
#
# @EXAMPLES:
#   # Run xwallpaper and print the image path on success
#   run "xwallpaper --zoom ${image}" "${image}"
#
#   # Restart compositor and show a success message
#   run --reload-compositor "xwallpaper --zoom ${image}" "Wallpaper updated" "Wallpaper failed"
#
#   # With success and failure hooks
#   run --on-success "notify-send 'OK'" \
#       --on-failure "notify-send 'Failed'" \
#       "cp config config.bak" "Backup complete" "Backup failed"

run() {
	relstat=0
	compstat=0

	while [ $# -gt 0 ]; do
		case "$1" in
			--reload-status) relstat=1 ;;
			--reload-compositor) compstat=1 ;;
			--on-success) success_command="${2}"; shift ;;
			--on-failure) failure_command="${2}"; shift ;;
			*) break;
		esac
		shift
	done

	if [ "${compstat}" -eq 1 ]; then
		pgrep -x picom > /dev/null && killall picom
	fi

	if ${1}; then
		[ -n "${2}" ] && echo "${2}"
		[ -n "${success_command}" ] && sh -c "${success_command}"
	else
		[ -n "${3}" ] && err "${3}"
		[ -n "${failure_command}" ] && sh -c "${failure_command}"
		exit 1
	fi

	if [ "${relstat}" -eq 1 ]; then
		slreload || echo "Warning: Failed to reload slstatus" >&2
	fi

	if [ "${compstat}" -eq 1 ]; then
    		picom -b || echo "Warning: Failed to start picom" >&2
	fi

	exit 0
}