bgnotify.plugin.zsh 2.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. #!/usr/bin/env zsh
  2. ## setup ##
  3. [[ -o interactive ]] || return #interactive only!
  4. zmodload zsh/datetime || { print "can't load zsh/datetime"; return } # faster than date()
  5. autoload -Uz add-zsh-hook || { print "can't add zsh hook!"; return }
  6. (( ${+bgnotify_threshold} )) || bgnotify_threshold=5 #default 10 seconds
  7. ## definitions ##
  8. if ! (type bgnotify_formatted | grep -q 'function'); then ## allow custom function override
  9. function bgnotify_formatted { ## args: (exit_status, command, elapsed_seconds)
  10. elapsed="$(( $3 % 60 ))s"
  11. (( $3 >= 60 )) && elapsed="$((( $3 % 3600) / 60 ))m $elapsed"
  12. (( $3 >= 3600 )) && elapsed="$(( $3 / 3600 ))h $elapsed"
  13. [ $1 -eq 0 ] && bgnotify "#win (took $elapsed)" "$2" || bgnotify "#fail (took $elapsed)" "$2"
  14. }
  15. fi
  16. }
  17. function currentAppId {
  18. if (( ${+commands[osascript]} )); then
  19. # output: com.googlecode.iterm2, 116
  20. osascript -e 'tell application (path to frontmost application as text) to get the {id, id of front window}' 2>/dev/null
  21. elif (( ${+commands[notify-send]} || ${+commands[kdialog]} )); then
  22. xprop -root 2> /dev/null | awk '/NET_ACTIVE_WINDOW/{print $5;exit} END{exit !$5}' || echo "0"
  23. else
  24. echo $EPOCHSECONDS
  25. fi
  26. }
  27. # currentAppId is expensive (more on macOS!) and it will remain the same until the shell is close
  28. bgnotify_termid=$(currentAppId)
  29. bgnotify () { ## args: (title, subtitle)
  30. if hash terminal-notifier 2>/dev/null; then #osx
  31. local term_id="${bgnotify_termid%%,*}" # remove window id
  32. if [[ -z "$term_id" ]]; then
  33. case "$TERM_PROGRAM" in
  34. iTerm.app) term_id='com.googlecode.iterm2' ;;
  35. Apple_Terminal) term_id='com.apple.terminal' ;;
  36. esac
  37. fi
  38. ## now call terminal-notifier, (hopefully with $term_id!)
  39. if [[ -z "$term_id" ]]; then
  40. terminal-notifier -message "$2" -title "$1" >/dev/null
  41. else
  42. terminal-notifier -message "$2" -title "$1" -activate "$term_id" -sender "$term_id" >/dev/null
  43. fi
  44. elif hash growlnotify 2>/dev/null; then #osx growl
  45. growlnotify -m "$1" "$2"
  46. elif hash notify-send 2>/dev/null; then #ubuntu gnome!
  47. notify-send "$1" "$2"
  48. elif hash kdialog 2>/dev/null; then #ubuntu kde!
  49. kdialog --title "$1" --passivepopup "$2" 5
  50. elif hash notifu 2>/dev/null; then #cygwyn support!
  51. notifu /m "$2" /p "$1"
  52. fi
  53. }
  54. ## Zsh hooks ##
  55. bgnotify_begin() {
  56. bgnotify_timestamp=$EPOCHSECONDS
  57. bgnotify_lastcmd="${1:-$2}"
  58. }
  59. bgnotify_end() {
  60. didexit=$?
  61. elapsed=$(( EPOCHSECONDS - bgnotify_timestamp ))
  62. past_threshold=$(( elapsed >= bgnotify_threshold ))
  63. if (( bgnotify_timestamp > 0 )) && (( past_threshold )); then
  64. if [[ $(currentAppId) != "$bgnotify_termid" ]]; then
  65. print -n "\a"
  66. bgnotify_formatted "$didexit" "$bgnotify_lastcmd" "$elapsed"
  67. fi
  68. fi
  69. bgnotify_timestamp=0 #reset it to 0!
  70. }
  71. ## only enable if a local (non-ssh) connection
  72. if [ -z "$SSH_CLIENT" ] && [ -z "$SSH_TTY" ]; then
  73. add-zsh-hook preexec bgnotify_begin
  74. add-zsh-hook precmd bgnotify_end
  75. fi