mirror of
https://github.com/philippdieter/zsh-auto-notify.git
synced 2025-10-13 03:58:44 +00:00

Option AUTO_NOTIFY_ENABLE_SSH has been added to enable and disable forwarding of notifications to local client for long running commands issued over SSH on remote servers.
204 lines
6.7 KiB
Bash
204 lines
6.7 KiB
Bash
export AUTO_NOTIFY_VERSION="0.10.2"
|
|
|
|
# Time it takes for a notification to expire
|
|
[[ -z "$AUTO_NOTIFY_EXPIRE_TIME" ]] &&
|
|
export AUTO_NOTIFY_EXPIRE_TIME=8000
|
|
# Threshold in seconds for when to automatically show a notification
|
|
[[ -z "$AUTO_NOTIFY_THRESHOLD" ]] &&
|
|
export AUTO_NOTIFY_THRESHOLD=10
|
|
# Enable or disable notifications for SSH sessions (0 = disabled, 1 = enabled)
|
|
[[ -z "$AUTO_NOTIFY_ENABLE_SSH" ]] &&
|
|
export AUTO_NOTIFY_ENABLE_SSH=0
|
|
|
|
# List of commands/programs to ignore sending notifications for
|
|
[[ -z "$AUTO_NOTIFY_IGNORE" ]] &&
|
|
export AUTO_NOTIFY_IGNORE=(
|
|
'vim'
|
|
'nvim'
|
|
'less'
|
|
'more'
|
|
'man'
|
|
'tig'
|
|
'watch'
|
|
'git commit'
|
|
'top'
|
|
'htop'
|
|
'ssh'
|
|
'nano'
|
|
)
|
|
|
|
function _auto_notify_format() {
|
|
local MESSAGE="$1"
|
|
local command="$2"
|
|
local elapsed="$3"
|
|
local exit_code="$4"
|
|
MESSAGE="${MESSAGE//\%command/$command}"
|
|
MESSAGE="${MESSAGE//\%elapsed/$elapsed}"
|
|
MESSAGE="${MESSAGE//\%exit_code/$exit_code}"
|
|
printf "%s" "$MESSAGE"
|
|
}
|
|
|
|
function _auto_notify_message() {
|
|
local command="$1"
|
|
local elapsed="$2"
|
|
local exit_code="$3"
|
|
local platform="$(uname)"
|
|
# Run using echo -e in order to make sure notify-send picks up new line
|
|
local DEFAULT_TITLE="\"%command\" Completed"
|
|
local DEFAULT_BODY="$(echo -e "Total time: %elapsed seconds\nExit code: %exit_code")"
|
|
|
|
local title="${AUTO_NOTIFY_TITLE:-$DEFAULT_TITLE}"
|
|
local text="${AUTO_NOTIFY_BODY:-$DEFAULT_BODY}"
|
|
|
|
title="$(_auto_notify_format "$title" "$command" "$elapsed" "$exit_code")"
|
|
body="$(_auto_notify_format "$text" "$command" "$elapsed" "$exit_code")"
|
|
|
|
if [[ "$platform" == "Linux" ]]; then
|
|
local urgency="normal"
|
|
local transient="--hint=int:transient:1"
|
|
local icon=${AUTO_NOTIFY_ICON_SUCCESS:-""}
|
|
# Exit code 130 is returned when a process is terminated with SIGINT.
|
|
# Since the user is already interacting with the program, there is no
|
|
# need to make the notification persistent.
|
|
if [[ "$exit_code" != "0" ]] && [[ "$exit_code" != "130" ]]; then
|
|
urgency="critical"
|
|
transient=""
|
|
icon=${AUTO_NOTIFY_ICON_FAILURE:-""}
|
|
fi
|
|
|
|
local arguments=("$title" "$body" "--app-name=zsh" "$transient" "--urgency=$urgency" "--expire-time=$AUTO_NOTIFY_EXPIRE_TIME")
|
|
|
|
if [[ -n "$icon" ]]; then
|
|
arguments+=("--icon=$icon")
|
|
fi
|
|
|
|
# Check if the script is running over SSH
|
|
if [[ -n "${SSH_CLIENT}" || -n "${SSH_CONNECTION}" ]]; then
|
|
# Extract the client IP address from environment
|
|
local client_ip="${SSH_CLIENT%% *}"
|
|
[[ -z "$client_ip" ]] && client_ip="${SSH_CONNECTION%% *}"
|
|
|
|
# Forward the notify-send command to the client machine via SSH
|
|
ssh "${USER}@${client_ip}" "$(printf '%q ' notify-send "${arguments[@]}")"
|
|
else
|
|
# If not running over SSH, send notification locally
|
|
notify-send "${arguments[@]}"
|
|
fi
|
|
|
|
elif [[ "$platform" == "Darwin" ]]; then
|
|
osascript \
|
|
-e 'on run argv' \
|
|
-e 'display notification (item 1 of argv) with title (item 2 of argv)' \
|
|
-e 'end run' \
|
|
"$body" "$title"
|
|
else
|
|
printf "Unknown platform for sending notifications: $platform\n"
|
|
printf "Please post an issue on gitub.com/MichaelAquilina/zsh-auto-notify/issues/\n"
|
|
fi
|
|
}
|
|
|
|
function _is_auto_notify_ignored() {
|
|
local command="$1"
|
|
# split the command if its been piped one or more times
|
|
local command_list=("${(@s/|/)command}")
|
|
local target_command="${command_list[-1]}"
|
|
# Remove leading whitespace
|
|
target_command="$(echo "$target_command" | sed -e 's/^ *//')"
|
|
|
|
# Ignore the command if running over SSH and AUTO_NOTIFY_ENABLE_SSH is disabled
|
|
if [[ -n ${SSH_CLIENT-} || -n ${SSH_TTY-} || -n ${SSH_CONNECTION-} ]] && [[ "${AUTO_NOTIFY_ENABLE_SSH-1}" == "0" ]]; then
|
|
print "yes"
|
|
return
|
|
fi
|
|
|
|
# Remove sudo prefix from command if detected
|
|
if [[ "$target_command" == "sudo "* ]]; then
|
|
target_command="${target_command/sudo /}"
|
|
fi
|
|
|
|
# If AUTO_NOTIFY_WHITELIST is defined, then auto-notify will ignore
|
|
# any item not defined in the white list
|
|
# Otherwise - the alternative (default) approach is used where the
|
|
# AUTO_NOTIFY_IGNORE blacklist is used to ignore commands
|
|
|
|
if [[ -n "$AUTO_NOTIFY_WHITELIST" ]]; then
|
|
for allowed in $AUTO_NOTIFY_WHITELIST; do
|
|
if [[ "$target_command" == "$allowed"* ]]; then
|
|
print "no"
|
|
return
|
|
fi
|
|
done
|
|
print "yes"
|
|
else
|
|
for ignore in $AUTO_NOTIFY_IGNORE; do
|
|
if [[ "$target_command" == "$ignore"* ]]; then
|
|
print "yes"
|
|
return
|
|
fi
|
|
done
|
|
print "no"
|
|
fi
|
|
}
|
|
|
|
function _auto_notify_send() {
|
|
# Immediately store the exit code before it goes away
|
|
local exit_code="$?"
|
|
|
|
if [[ -z "$AUTO_COMMAND" && -z "$AUTO_COMMAND_START" ]]; then
|
|
return
|
|
fi
|
|
|
|
if [[ "$(_is_auto_notify_ignored "$AUTO_COMMAND_FULL")" == "no" ]]; then
|
|
local current="$(date +"%s")"
|
|
let "elapsed = current - AUTO_COMMAND_START"
|
|
|
|
if [[ $elapsed -gt $AUTO_NOTIFY_THRESHOLD ]]; then
|
|
_auto_notify_message "$AUTO_COMMAND" "$elapsed" "$exit_code"
|
|
fi
|
|
fi
|
|
|
|
# Empty tracking so that notifications are not
|
|
# triggered for any commands not run (e.g ctrl+C when typing)
|
|
_auto_notify_reset_tracking
|
|
}
|
|
|
|
function _auto_notify_track() {
|
|
# $1 is the string the user typed, but only when history is enabled
|
|
# $2 is a single-line, size-limited version of the command that is always available
|
|
# To still do something useful when history is disabled, although with reduced functionality, fall back to $2 when $1 is empty
|
|
AUTO_COMMAND="${1:-$2}"
|
|
AUTO_COMMAND_FULL="$3"
|
|
AUTO_COMMAND_START="$(date +"%s")"
|
|
}
|
|
|
|
function _auto_notify_reset_tracking() {
|
|
# Command start time in seconds since epoch
|
|
unset AUTO_COMMAND_START
|
|
# Full command that the user has executed after alias expansion
|
|
unset AUTO_COMMAND_FULL
|
|
# Command that the user has executed
|
|
unset AUTO_COMMAND
|
|
}
|
|
|
|
function disable_auto_notify() {
|
|
add-zsh-hook -D preexec _auto_notify_track
|
|
add-zsh-hook -D precmd _auto_notify_send
|
|
}
|
|
|
|
function enable_auto_notify() {
|
|
autoload -Uz add-zsh-hook
|
|
add-zsh-hook preexec _auto_notify_track
|
|
add-zsh-hook precmd _auto_notify_send
|
|
}
|
|
|
|
_auto_notify_reset_tracking
|
|
|
|
|
|
platform="$(uname)"
|
|
if [[ "$platform" == "Linux" ]] && ! type notify-send > /dev/null; then
|
|
printf "'notify-send' must be installed for zsh-auto-notify to work\n"
|
|
printf "Please install it with your relevant package manager\n"
|
|
else
|
|
enable_auto_notify
|
|
fi
|