3 # This script prints a bell character when a command finishes
4 # if it has been running for longer than $zbell_duration seconds.
5 # If there are programs that you know run long that you don't
6 # want to bell after, then add them to $zbell_ignore.
8 # This script uses only zsh builtins so its fast, there's no needless
9 # forking, and its only dependency is zsh and its standard modules
11 # Written by Jean-Philippe Ouellet <jpo@vt.edu>
12 # Made available under the ISC license.
14 # only do this if we're in an interactive shell
15 [[ -o interactive ]] || return
17 # get $EPOCHSECONDS. builtins are faster than date(1)
18 zmodload zsh/datetime || return
20 # make sure we can register hooks
21 autoload -Uz add-zsh-hook || return
23 # make sure we can do regexp replace
24 autoload -Uz regexp-replace || return
26 # initialize zbell_duration if not set
27 (( ${+zbell_duration} )) || zbell_duration=15
29 # initialize zbell_ignore if not set
30 (( ${+zbell_ignore} )) || zbell_ignore=($EDITOR $PAGER)
32 # initialize zbell_use_notify_send if not set
33 (( ${+zbell_use_notify_send} )) || zbell_use_notify_send=true
35 # initialize it because otherwise we compare a date and an empty string
36 # the first time we see the prompt. it's fine to have lastcmd empty on the
37 # initial run because it evaluates to an empty string, and splitting an
38 # empty string just results in an empty array.
39 zbell_timestamp=$EPOCHSECONDS
41 # UI notification function
43 # $2: duration in seconds
45 [[ $zbell_use_notify_send != "true" ]] && return
47 if type notify-send > /dev/null; then
48 notify-send -i terminal "Command completed in ${2}s:" $1
52 # default notification function
54 # $2: duration in seconds
56 zbell_ui_notify "${@}"
60 # right before we begin to execute something, store the time it started at
62 zbell_timestamp=$EPOCHSECONDS
66 # when it finishes, if it's been running longer than $zbell_duration,
67 # and we dont have an ignored command in the line, then print a bell.
69 local cmd_duration=$(( $EPOCHSECONDS - $zbell_timestamp ))
70 local ran_long=$(( $cmd_duration >= $zbell_duration ))
72 local zbell_lastcmd_tmp="$zbell_lastcmd"
73 regexp-replace zbell_lastcmd_tmp '^sudo ' ''
75 [[ $zbell_last_timestamp == $zbell_timestamp ]] && return
77 [[ $zbell_lastcmd_tmp == "" ]] && return
79 zbell_last_timestamp=$zbell_timestamp
81 local has_ignored_cmd=0
82 for cmd in ${(s:;:)zbell_lastcmd_tmp//|/;}; do
85 if (( ${zbell_ignore[(i)$util]} <= ${#zbell_ignore} )); then
91 (( ! $has_ignored_cmd && ran_long )) && zbell_notify $zbell_lastcmd $cmd_duration
94 # register the functions as hooks
95 add-zsh-hook preexec zbell_begin
96 add-zsh-hook precmd zbell_end