From 523b75e1e463902abcd4b60922dd4b3ca1583a03 Mon Sep 17 00:00:00 2001 From: Alex Reece Date: Thu, 13 Jun 2013 01:28:53 -0400 Subject: [PATCH 1/9] add awreece prompt --- modules/prompt/functions/prompt_awreece_setup | 168 ++++++++++++++++++ 1 file changed, 168 insertions(+) create mode 100644 modules/prompt/functions/prompt_awreece_setup diff --git a/modules/prompt/functions/prompt_awreece_setup b/modules/prompt/functions/prompt_awreece_setup new file mode 100644 index 0000000000..2dcb1e541a --- /dev/null +++ b/modules/prompt/functions/prompt_awreece_setup @@ -0,0 +1,168 @@ +# +# A simple theme that displays relevant, contextual information. +# +# Authors: +# Alex Reece +# +# Screenshots: +# http://codearcana.com/posts/2013/11/06/my-zsh-theme.html +# http://codearcana.com/images/zsh_theme.png +# + +function prompt_awreece_help { +cat </dev/null + fi +} + +# Return a zero exit status (true) iff the current shell is controlled via ssh. +function prompt_awreece_is_ssh { + # Actually, sudo etc clear a bunch of environment variables, including + # SSH_CONNECTION, so this doesn't always work. Unfortunately, I don't know + # the best way to make it work. For now, I'll hide it in a function and I can + # update it when I figure out a better way later. + [[ -n $SSH_CONNECTION ]] +} + +function prompt_awreece_preview { + local +h PROMPT='%# ' + local +h RPROMPT='' + # Set a last_run_time to make it interesting. + local +h last_run_time=3.14159 + + prompt_preview_theme 'awreece' "$@" +} + +prompt_awreece_setup "$@" From 171b41d3c46ce5b6ebd8ef492e38a1ac514a928d Mon Sep 17 00:00:00 2001 From: Alex Reece Date: Thu, 13 Jun 2013 02:40:13 -0400 Subject: [PATCH 2/9] set necessary prompt_opts --- modules/prompt/functions/prompt_awreece_setup | 2 ++ 1 file changed, 2 insertions(+) diff --git a/modules/prompt/functions/prompt_awreece_setup b/modules/prompt/functions/prompt_awreece_setup index 2dcb1e541a..0ebb3b3bda 100644 --- a/modules/prompt/functions/prompt_awreece_setup +++ b/modules/prompt/functions/prompt_awreece_setup @@ -37,6 +37,8 @@ EOH } function prompt_awreece_setup { + prompt_opts=(cr percent subst) + # Load required functions. autoload -Uz add-zsh-hook zmodload zsh/datetime # For EPOCHREALTIME. From 856b3ff61421a75fad3938ba34d8cfb45362cf26 Mon Sep 17 00:00:00 2001 From: Alex Reece Date: Thu, 13 Jun 2013 03:48:24 -0400 Subject: [PATCH 3/9] refactor into modules --- modules/last_command/README.md | 29 ++++++ modules/last_command/functions/time_to_human | 26 +++++ modules/last_command/init.zsh | 39 ++++++++ modules/notify/README.md | 19 ++++ modules/notify/init.zsh | 60 +++++++++++ modules/prompt/functions/prompt_awreece_setup | 99 +------------------ 6 files changed, 178 insertions(+), 94 deletions(-) create mode 100644 modules/last_command/README.md create mode 100644 modules/last_command/functions/time_to_human create mode 100644 modules/last_command/init.zsh create mode 100644 modules/notify/README.md create mode 100644 modules/notify/init.zsh diff --git a/modules/last_command/README.md b/modules/last_command/README.md new file mode 100644 index 0000000000..66b42868e8 --- /dev/null +++ b/modules/last_command/README.md @@ -0,0 +1,29 @@ +Last Command +============ + +Provides information about the last command run. + +Exported variables +------------------ + +- `last_command`: The string of the last command. +- `last_command_time`: The execution time (in floating point seconds) of the + last command. +- `last_command_status`: The exit status of the last command. + + +Exported functions +------------------ + +- `time_to_human`: Prints a floating point time duration in seconds. + + +Authors +------- + +*The authors of this module should be contacted via the [issue tracker][1].* + + - [Alex Reece](https://github.com/awreece) + +[1]: https://github.com/awreece/prezto/issues + diff --git a/modules/last_command/functions/time_to_human b/modules/last_command/functions/time_to_human new file mode 100644 index 0000000000..8a8242e373 --- /dev/null +++ b/modules/last_command/functions/time_to_human @@ -0,0 +1,26 @@ +# +# Pretty prints a time in human readable format. +# +# Authors: +# Alex Reece +# + +# Converts a floating point time duration in seconds to a human readable string. +function time_to_human { + seconds=$1 + if (( seconds < 10 )); then + printf "%6.3fs" $seconds + elif (( seconds < 60 )); then + printf "%6.3fs" $seconds + elif (( seconds < (60*60) )); then + printf "%6.3fm" $(( seconds / 60 )) + elif (( seconds < (60*60*24) )); then + printf "%6.3fh" $(( seconds / (60*60) )) + elif (( seconds < (60*60*24*30) )); then + printf "%6.3fd" $(( seconds / (60*60*24) )) + elif (( seconds < (60*60*24*30*12) )); then + printf "%6.3fm" $(( seconds / (60*60*24*30) )) + else + printf "%6.3fy" $(( seconds / (60*60*24*30*12) )) + fi +} diff --git a/modules/last_command/init.zsh b/modules/last_command/init.zsh new file mode 100644 index 0000000000..28e312e590 --- /dev/null +++ b/modules/last_command/init.zsh @@ -0,0 +1,39 @@ +# +# Exports information about the last command. +# +# Authors: +# Alex Reece +# + +# Exported values. +last_command='' +last_command_status=0 +last_command_time=0.0 + +# Not exported. +last_command_start_time=invalid + +zmodload zsh/datetime # For EPOCHREALTIME. + +function last_command_precmd { + exit_status=$? # TODO(awreece) What happens if another precmd runs first? + + # We do these 'invalid' shenanigans because zsh executes precmd but not + # preexec if an empty line is entered. + if [[ $last_command_start_time != 'invalid' ]]; then + last_command_status=$exit_status + last_command_time=$((EPOCHREALTIME - last_command_start_time)) + + last_command_start_time='invalid' + fi +} + +function last_command_preexec { + last_command_start_time=$EPOCHREALTIME + last_command=$1 +} + +autoload -Uz add-zsh-hook + +add-zsh-hook precmd last_command_precmd +add-zsh-hook preexec last_command_preexec diff --git a/modules/notify/README.md b/modules/notify/README.md new file mode 100644 index 0000000000..6cf06eb94e --- /dev/null +++ b/modules/notify/README.md @@ -0,0 +1,19 @@ +Last Command +============ + +Notifies if the command completes and terminal isn't the foreground window. + +Caveats +------- +Currently only works on Mac OSX with `terminal-notifier`. At some point, I +will add support for other notification mechanisms. + +Authors +------- + +*The authors of this module should be contacted via the [issue tracker][1].* + + - [Alex Reece](https://github.com/awreece) + +[1]: https://github.com/awreece/prezto/issues + diff --git a/modules/notify/init.zsh b/modules/notify/init.zsh new file mode 100644 index 0000000000..58415564d1 --- /dev/null +++ b/modules/notify/init.zsh @@ -0,0 +1,60 @@ +# Notifies if the last command completes and terminal window is not in +# foreground. +# +# Authors: +# Alex Reece +# + +pmodload 'last_command' + +if [[ "$OSTYPE" == darwin* ]]; then + terminal_window_id=$(osascript -e 'tell application "Terminal" to ¬' \ + -e ' get id of front window') +fi + +# Returns true if the current window has focus. +# Warning: Currently only implementd on mac. +# Assume $terminal_window_id is the osascript id of the current window. +# +# TODO(awreece) Add support for tabs. +function window_is_focused { + if [[ "$OSTYPE" == darwin* ]]; then + focus_window_id=$(osascript -e 'tell application "System Events" to ¬' \ + -e ' set focus_app_name to ¬' \ + -e ' name of first application process ¬' \ + -e ' whose frontmost is true' \ + -e 'tell application focus_app_name to ¬' \ + -e ' get id of front window') + fi + # On a not mac, this will always return true since focus_id and + # terminal_window_id are both undefined so empty strings. + [[ $focus_window_id == $terminal_window_id ]] +} + +# Sends a notification that the last command terminated. +# Warning: currently only implemented for mac. +function last_command_notify { + message=$(printf "Command \"%s\" finished (%d) after %s." \ + $last_command \ + $last_command_status \ + $(time_to_human $last_command_time)) + + # TODO(awreece) Add support for user defined callback. + if [[ "$OSTYPE" == darwin* ]]; then + callback="osascript -e 'tell application \"Terminal\"' \ + -e 'activate' \ + -e 'set index of window id $terminal_window_id to 1' \ + -e 'end tell'" + terminal-notifier -message $message -execute $callback >/dev/null + fi +} + +function notify_precmd { + if ! window_is_focused; then + last_command_notify + fi +} + +autoload -Uz add-zsh-hook + +add-zsh-hook precmd notify_precmd diff --git a/modules/prompt/functions/prompt_awreece_setup b/modules/prompt/functions/prompt_awreece_setup index 0ebb3b3bda..3115de8a40 100644 --- a/modules/prompt/functions/prompt_awreece_setup +++ b/modules/prompt/functions/prompt_awreece_setup @@ -39,22 +39,8 @@ EOH function prompt_awreece_setup { prompt_opts=(cr percent subst) - # Load required functions. - autoload -Uz add-zsh-hook - zmodload zsh/datetime # For EPOCHREALTIME. - - # Add hooks used for timing each command and displaying notifications. - add-zsh-hook precmd prompt_awreece_precmd - add-zsh-hook preexec prompt_awreece_preexec - - last_run_time=0 - last_start_time='invalid' - last_command='' - last_status=0 - if [[ "$OSTYPE" == darwin* ]]; then - terminal_window_id=$(osascript -e 'tell application "Terminal" to ¬' \ - -e ' get id of front window') - fi + # Load prerequisites. + pmodload 'last_command' # Variables used for prompts. local background_job_status='%(1j.%F{yellow}%j&%f .)' @@ -70,83 +56,8 @@ function prompt_awreece_setup { RPROMPT="${background_job_status}${full_directory}${ssh_host}${command_time}" } -# Converts a floating point time in seconds to a human readable string. -function prompt_awreece_time_to_human { - seconds=$1 - if (( seconds < 10 )); then - printf "%6.3fs" $seconds - elif (( seconds < 60 )); then - printf "%6.3fs" $seconds - elif (( seconds < (60*60) )); then - printf "%6.3fm" $(( seconds / 60 )) - elif (( seconds < (60*60*24) )); then - printf "%6.3fh" $(( seconds / (60*60) )) - else - printf "%6.3fd" $(( seconds / (60*60*24) )) - fi -} - function prompt_awreece_command_time { - prompt_awreece_time_to_human $last_run_time -} - -function prompt_awreece_preexec { - last_start_time=$EPOCHREALTIME - last_command=$1 -} - -function prompt_awreece_precmd { - exit_status=$? # TODO(awreece) What happens if another precmd runs first? - - # We do these 'invalid' shenanigans because zsh executes precmd but not - # preexec if an empty line is entered. - if [[ $last_start_time != 'invalid' ]]; then - last_status=$exit_status - last_run_time=$((EPOCHREALTIME - last_start_time)) - - if ! prompt_awreece_is_focused; then - prompt_awreece_notify - fi - - last_start_time='invalid' - last_comamnd='' - fi -} - -# Returns true if the current window has focus. -# Warning: Currently only implementd on mac. -# Assume $terminal_window_id is the osascript id of the current window. -# -# TODO(awreece) Add support for tabs. -function prompt_awreece_is_focused { - if [[ "$OSTYPE" == darwin* ]]; then - focus_window_id=$(osascript -e 'tell application "System Events" to ¬' \ - -e ' set focus_app_name to ¬' \ - -e ' name of first application process ¬' \ - -e ' whose frontmost is true' \ - -e 'tell application focus_app_name to ¬' \ - -e ' get id of front window') - fi - # On a not mac, this will always return true since focus_id and - # terminal_window_id are both undefined so empty strings. - [[ $focus_window_id == $terminal_window_id ]] -} - -# Sends a notification that the last command terminated. -# Warning: currently only implemented for mac. -function prompt_awreece_notify { - message=$(printf "Command \"%s\" finished (%d) after %s." \ - $last_command \ - $last_status \ - $(prompt_awreece_time_to_human $last_run_time)) - - if [[ "$OSTYPE" == darwin* ]]; then - callback="osascript -e 'tell application \"Terminal\"' \ - -e 'activate' \ - -e 'set index of window id $terminal_window_id to 1' \ - -e 'end tell'" - terminal-notifier -message $message -execute $callback >/dev/null - fi + time_to_human $last_command_time } # Return a zero exit status (true) iff the current shell is controlled via ssh. @@ -161,8 +72,8 @@ function prompt_awreece_is_ssh { function prompt_awreece_preview { local +h PROMPT='%# ' local +h RPROMPT='' - # Set a last_run_time to make it interesting. - local +h last_run_time=3.14159 + # Set a last_command_time to make it interesting. + local +h last_commmand_time=3.14159 prompt_preview_theme 'awreece' "$@" } From f99f480eee9a392d93ceec7633b28de828d2f8bd Mon Sep 17 00:00:00 2001 From: Alex Reece Date: Thu, 13 Jun 2013 12:19:10 -0400 Subject: [PATCH 4/9] add linux support --- modules/notify/functions/focused_window_id | 26 +++++++++++ .../functions/should_load_notify_module | 34 ++++++++++++++ modules/notify/init.zsh | 44 +++++++++---------- 3 files changed, 81 insertions(+), 23 deletions(-) create mode 100644 modules/notify/functions/focused_window_id create mode 100644 modules/notify/functions/should_load_notify_module diff --git a/modules/notify/functions/focused_window_id b/modules/notify/functions/focused_window_id new file mode 100644 index 0000000000..afdb850e0b --- /dev/null +++ b/modules/notify/functions/focused_window_id @@ -0,0 +1,26 @@ +# Gets the id of the current focused window. +# +# Authors: +# Alex Reece +# + +function focused_window_id { + case "$OSTYPE" in + (darwin*) + osascript -e 'tell application "System Events" to ¬' \ + -e ' set focus_app_name to ¬' \ + -e ' name of first application process ¬' \ + -e ' whose frontmost is true' \ + -e 'tell application focus_app_name to ¬' \ + -e ' get id of front window' + ;; + (linux-gnu*) + # http://stackoverflow.com/a/8688624/447288 + xprop -root -f _NET_ACTIVE_WINDOW 0x ' $0' _NET_ACTIVE_WINDOW \ + | awk '{print $2}' + ;; + (*) + return 1 + ;; + esac +} diff --git a/modules/notify/functions/should_load_notify_module b/modules/notify/functions/should_load_notify_module new file mode 100644 index 0000000000..93a2359f17 --- /dev/null +++ b/modules/notify/functions/should_load_notify_module @@ -0,0 +1,34 @@ +# Check if it makes sense to load the notify module. +# +# Checks for requirements, that it is an xsession, etc. +# +# Authors: +# Alex Reece +# + +function should_load_notify_module { + case "$OSTYPE" in + (darwin*) + # For now, always enable on mac osx. + # TODO(awreece) Disable if ssh with no windows? + return 0 + ;; + (linux-gnu*) + # Disable if don't have X. + if [[ -z $XAUTHORITY ]]; then + return 1 + fi + + # We need both of these functions to operate. + if (( ! $+commands[notify-send] || ! $+commands[xprop] )); then + return 1 + fi + + return 0 + ;; + (*) + # If we don't know, then just disable. + return 1 + ;; + esac +} diff --git a/modules/notify/init.zsh b/modules/notify/init.zsh index 58415564d1..b5cab9205d 100644 --- a/modules/notify/init.zsh +++ b/modules/notify/init.zsh @@ -7,28 +7,18 @@ pmodload 'last_command' -if [[ "$OSTYPE" == darwin* ]]; then - terminal_window_id=$(osascript -e 'tell application "Terminal" to ¬' \ - -e ' get id of front window') +if ! should_load_notify_module; then + return 1 fi +# Initialize $terminal_window_id to the current active window. +terminal_window_id=$(focused_window_id) + # Returns true if the current window has focus. -# Warning: Currently only implementd on mac. -# Assume $terminal_window_id is the osascript id of the current window. # # TODO(awreece) Add support for tabs. function window_is_focused { - if [[ "$OSTYPE" == darwin* ]]; then - focus_window_id=$(osascript -e 'tell application "System Events" to ¬' \ - -e ' set focus_app_name to ¬' \ - -e ' name of first application process ¬' \ - -e ' whose frontmost is true' \ - -e 'tell application focus_app_name to ¬' \ - -e ' get id of front window') - fi - # On a not mac, this will always return true since focus_id and - # terminal_window_id are both undefined so empty strings. - [[ $focus_window_id == $terminal_window_id ]] + [[ $(focused_window_id) == $terminal_window_id ]] } # Sends a notification that the last command terminated. @@ -40,13 +30,21 @@ function last_command_notify { $(time_to_human $last_command_time)) # TODO(awreece) Add support for user defined callback. - if [[ "$OSTYPE" == darwin* ]]; then - callback="osascript -e 'tell application \"Terminal\"' \ - -e 'activate' \ - -e 'set index of window id $terminal_window_id to 1' \ - -e 'end tell'" - terminal-notifier -message $message -execute $callback >/dev/null - fi + case "$OSTYPE" in + (darwin*) + callback="osascript -e 'tell application \"Terminal\"' \ + -e 'activate' \ + -e 'set index of window id $terminal_window_id to 1' \ + -e 'end tell'" + terminal-notifier -message $message -execute $callback >/dev/null + ;; + (linux-gnu*) + notify-send "Command finished" $message + ;; + (*) + return 1 + ;; + esac } function notify_precmd { From 36559d9978b773264ca65e77529ac77d1b933a3b Mon Sep 17 00:00:00 2001 From: Alex Reece Date: Thu, 13 Jun 2013 16:22:53 -0400 Subject: [PATCH 5/9] Add changes from sorin codereview - autoload functions aren't surrounded in an addition function { } - export cross platform notify function - control notify behavior with zstyles --- modules/last_command/functions/time_to_human | 34 +++++------ modules/last_command/init.zsh | 11 ++-- modules/node/init.zsh | 2 + modules/notify/README.md | 26 ++++++-- modules/notify/functions/focused_window_id | 38 ++++++------ modules/notify/functions/notify | 27 +++++++++ modules/notify/functions/notify_last_command | 40 +++++++++++++ modules/notify/functions/should_auto_notify | 35 +++++++++++ .../functions/should_load_notify_module | 34 ----------- modules/notify/init.zsh | 59 ++++--------------- 10 files changed, 179 insertions(+), 127 deletions(-) create mode 100644 modules/notify/functions/notify create mode 100644 modules/notify/functions/notify_last_command create mode 100644 modules/notify/functions/should_auto_notify delete mode 100644 modules/notify/functions/should_load_notify_module diff --git a/modules/last_command/functions/time_to_human b/modules/last_command/functions/time_to_human index 8a8242e373..79133776ad 100644 --- a/modules/last_command/functions/time_to_human +++ b/modules/last_command/functions/time_to_human @@ -6,21 +6,19 @@ # # Converts a floating point time duration in seconds to a human readable string. -function time_to_human { - seconds=$1 - if (( seconds < 10 )); then - printf "%6.3fs" $seconds - elif (( seconds < 60 )); then - printf "%6.3fs" $seconds - elif (( seconds < (60*60) )); then - printf "%6.3fm" $(( seconds / 60 )) - elif (( seconds < (60*60*24) )); then - printf "%6.3fh" $(( seconds / (60*60) )) - elif (( seconds < (60*60*24*30) )); then - printf "%6.3fd" $(( seconds / (60*60*24) )) - elif (( seconds < (60*60*24*30*12) )); then - printf "%6.3fm" $(( seconds / (60*60*24*30) )) - else - printf "%6.3fy" $(( seconds / (60*60*24*30*12) )) - fi -} +seconds=$1 +if (( seconds < 10 )); then + printf "%6.3fs" $seconds +elif (( seconds < 60 )); then + printf "%6.3fs" $seconds +elif (( seconds < (60*60) )); then + printf "%6.3fm" $(( seconds / 60 )) +elif (( seconds < (60*60*24) )); then + printf "%6.3fh" $(( seconds / (60*60) )) +elif (( seconds < (60*60*24*30) )); then + printf "%6.3fd" $(( seconds / (60*60*24) )) +elif (( seconds < (60*60*24*30*12) )); then + printf "%6.3fm" $(( seconds / (60*60*24*30) )) +else + printf "%6.3fy" $(( seconds / (60*60*24*30*12) )) +fi diff --git a/modules/last_command/init.zsh b/modules/last_command/init.zsh index 28e312e590..34f07c28da 100644 --- a/modules/last_command/init.zsh +++ b/modules/last_command/init.zsh @@ -1,20 +1,21 @@ # -# Exports information about the last command. +# Provides information about the last command. # # Authors: # Alex Reece # -# Exported values. +# Provided values. last_command='' last_command_status=0 last_command_time=0.0 -# Not exported. -last_command_start_time=invalid - zmodload zsh/datetime # For EPOCHREALTIME. +# This value is used internally by this module and is not intended to be used +# elsewhere. +last_command_start_time='invalid' + function last_command_precmd { exit_status=$? # TODO(awreece) What happens if another precmd runs first? diff --git a/modules/node/init.zsh b/modules/node/init.zsh index 904d24d931..62d434dcc6 100644 --- a/modules/node/init.zsh +++ b/modules/node/init.zsh @@ -16,6 +16,8 @@ if (( ! $+commands[node] )); then return 1 fi +pmodload 'helper' + # Load NPM completion. if (( $+commands[npm] )); then cache_file="${0:h}/cache.zsh" diff --git a/modules/notify/README.md b/modules/notify/README.md index 6cf06eb94e..0ffe77f595 100644 --- a/modules/notify/README.md +++ b/modules/notify/README.md @@ -3,10 +3,28 @@ Last Command Notifies if the command completes and terminal isn't the foreground window. -Caveats -------- -Currently only works on Mac OSX with `terminal-notifier`. At some point, I -will add support for other notification mechanisms. +Settings +-------- + +### Growl + +By default, `notify` will use the Notification Center on Mac OSX via +`terminal-notifier` and will fall back to Growl if this is not available. To +force the use of growl, add the following to *zpreztorc*. + + zstyle ':prezto:module:notify' force-growl 'yes' + +### Auto-notify if window not focused + +This module can automatically notify if a (long running) command completes +while the terminal window does not have focus. This will pop up a notification +with information about the last command like this: + +![Last command notification](http://codearcana.com/images/zsh_theme_popup.png) + +To enable this feature, add the following to *zpreztorc*: + + zstyle ':prezto:module:notify' auto-notify 'yes' Authors ------- diff --git a/modules/notify/functions/focused_window_id b/modules/notify/functions/focused_window_id index afdb850e0b..e7c63e2f75 100644 --- a/modules/notify/functions/focused_window_id +++ b/modules/notify/functions/focused_window_id @@ -4,23 +4,21 @@ # Alex Reece # -function focused_window_id { - case "$OSTYPE" in - (darwin*) - osascript -e 'tell application "System Events" to ¬' \ - -e ' set focus_app_name to ¬' \ - -e ' name of first application process ¬' \ - -e ' whose frontmost is true' \ - -e 'tell application focus_app_name to ¬' \ - -e ' get id of front window' - ;; - (linux-gnu*) - # http://stackoverflow.com/a/8688624/447288 - xprop -root -f _NET_ACTIVE_WINDOW 0x ' $0' _NET_ACTIVE_WINDOW \ - | awk '{print $2}' - ;; - (*) - return 1 - ;; - esac -} +case "$OSTYPE" in + (darwin*) + osascript -e 'tell application "System Events" to ¬' \ + -e ' set focus_app_name to ¬' \ + -e ' name of first application process ¬' \ + -e ' whose frontmost is true' \ + -e 'tell application focus_app_name to ¬' \ + -e ' get id of front window' + ;; + (linux-gnu*) + # http://stackoverflow.com/a/8688624/447288 + xprop -root -f _NET_ACTIVE_WINDOW 0x ' $0' _NET_ACTIVE_WINDOW \ + | awk '{print $2}' + ;; + (*) + return 1 + ;; +esac diff --git a/modules/notify/functions/notify b/modules/notify/functions/notify new file mode 100644 index 0000000000..d0502e0778 --- /dev/null +++ b/modules/notify/functions/notify @@ -0,0 +1,27 @@ +# Pops up a notification with the provided arg. +# +# Authors: +# Alex Reece +# + +# I actually want all the args as one string. +message="$*" + +case "$OSTYPE" in + (darwin*) + if is-callable terminal-notifier && \ + ! zstyle -t ':prezto:module:notify' force-growl; then + terminal-notifier >/dev/null -message $message + elif is-callable growlnotify; then + growlnotify --message $message + else + return 1 + fi + ;; + (linux-gnu*) + notify-send $message + ;; + (*) + return 1 + ;; +esac diff --git a/modules/notify/functions/notify_last_command b/modules/notify/functions/notify_last_command new file mode 100644 index 0000000000..f27fe0cbd4 --- /dev/null +++ b/modules/notify/functions/notify_last_command @@ -0,0 +1,40 @@ +# Sends a notification that the last command completed. +# +# Assumes $terminal_window_id is the id of the terminals window and that +# last_comand module is loaded. +# +# Authors: +# Alex Reece +# + +message=$(printf "Command \"%s\" finished (%d) after %s." \ + $last_command \ + $last_command_status \ + $(time_to_human $last_command_time)) + +# We duplicate a lot of the functionality of notify, but it means we can +# have this nifty callback to select the window that finished. + +# TODO(awreece) Add support for user defined callback. +case "$OSTYPE" in + (darwin*) + if is-callable terminal-notifier && + ! zstyle -t ':prezto:module:notify' force-growl; then + callback="osascript -e 'tell application \"Terminal\"' \ + -e 'activate' \ + -e 'set index of window id $terminal_window_id to 1' \ + -e 'end tell'" + terminal-notifier -message $message -execute $callback >/dev/null + elif is-callable growlnotify; then + growlnotify --message $message + else + return 1 + fi + ;; + (linux-gnu*) + notify-send "Command finished" $message + ;; + (*) + return 1 + ;; +esac diff --git a/modules/notify/functions/should_auto_notify b/modules/notify/functions/should_auto_notify new file mode 100644 index 0000000000..1edfcccb06 --- /dev/null +++ b/modules/notify/functions/should_auto_notify @@ -0,0 +1,35 @@ +# Check if it makes sense to load the notify module. +# +# Checks for requirements, that it is an xsession, etc. +# +# Authors: +# Alex Reece +# + +if ! zstyle -t ':prezto:module:notify' auto-notify; then + return 1 +fi + +case "$OSTYPE" in + (darwin*) + # TODO(awreece) Disable if ssh with no windows? + is-callable terminal-notifier || is-callable growlnotify + ;; + (linux-gnu*) + # Disable if don't have X. + if [[ -z $XAUTHORITY ]]; then + return 1 + fi + + # We need both of these functions to operate. + if (( ! $+commands[notify-send] || ! $+commands[xprop] )); then + return 1 + fi + + return 0 + ;; + (*) + # If we don't know, then just disable. + return 1 + ;; +esac diff --git a/modules/notify/functions/should_load_notify_module b/modules/notify/functions/should_load_notify_module deleted file mode 100644 index 93a2359f17..0000000000 --- a/modules/notify/functions/should_load_notify_module +++ /dev/null @@ -1,34 +0,0 @@ -# Check if it makes sense to load the notify module. -# -# Checks for requirements, that it is an xsession, etc. -# -# Authors: -# Alex Reece -# - -function should_load_notify_module { - case "$OSTYPE" in - (darwin*) - # For now, always enable on mac osx. - # TODO(awreece) Disable if ssh with no windows? - return 0 - ;; - (linux-gnu*) - # Disable if don't have X. - if [[ -z $XAUTHORITY ]]; then - return 1 - fi - - # We need both of these functions to operate. - if (( ! $+commands[notify-send] || ! $+commands[xprop] )); then - return 1 - fi - - return 0 - ;; - (*) - # If we don't know, then just disable. - return 1 - ;; - esac -} diff --git a/modules/notify/init.zsh b/modules/notify/init.zsh index b5cab9205d..6993a4c810 100644 --- a/modules/notify/init.zsh +++ b/modules/notify/init.zsh @@ -5,54 +5,21 @@ # Alex Reece # -pmodload 'last_command' +pmodload 'helper' -if ! should_load_notify_module; then - return 1 -fi - -# Initialize $terminal_window_id to the current active window. -terminal_window_id=$(focused_window_id) - -# Returns true if the current window has focus. -# -# TODO(awreece) Add support for tabs. -function window_is_focused { - [[ $(focused_window_id) == $terminal_window_id ]] -} - -# Sends a notification that the last command terminated. -# Warning: currently only implemented for mac. -function last_command_notify { - message=$(printf "Command \"%s\" finished (%d) after %s." \ - $last_command \ - $last_command_status \ - $(time_to_human $last_command_time)) +if should_auto_notify; then + pmodload 'last_command' - # TODO(awreece) Add support for user defined callback. - case "$OSTYPE" in - (darwin*) - callback="osascript -e 'tell application \"Terminal\"' \ - -e 'activate' \ - -e 'set index of window id $terminal_window_id to 1' \ - -e 'end tell'" - terminal-notifier -message $message -execute $callback >/dev/null - ;; - (linux-gnu*) - notify-send "Command finished" $message - ;; - (*) - return 1 - ;; - esac -} + # Initialize $terminal_window_id to the current active window. + terminal_window_id=$(focused_window_id) -function notify_precmd { - if ! window_is_focused; then - last_command_notify - fi -} + function notify_precmd { + if [[ $(focused_window_id) != $terminal_window_id ]]; then + notify_last_command + fi + } -autoload -Uz add-zsh-hook + autoload -Uz add-zsh-hook -add-zsh-hook precmd notify_precmd + add-zsh-hook precmd notify_precmd +fi From ba4167d89e830f370f258ee53242bffdb827b25c Mon Sep 17 00:00:00 2001 From: Alex Reece Date: Thu, 13 Jun 2013 17:24:06 -0400 Subject: [PATCH 6/9] better documentation for notify --- modules/notify/README.md | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/modules/notify/README.md b/modules/notify/README.md index 0ffe77f595..17fa482ff2 100644 --- a/modules/notify/README.md +++ b/modules/notify/README.md @@ -1,7 +1,12 @@ -Last Command -============ +Notify +====== -Notifies if the command completes and terminal isn't the foreground window. +Cross platform notification support. + +Functions +--------- + +- `notify` opens a notification with the given args. Usage: `notify hello world`. Settings -------- From 0578d19d06a88d8cbb7d00d109f4d9605774d2ef Mon Sep 17 00:00:00 2001 From: Alex Reece Date: Thu, 13 Jun 2013 22:19:49 -0400 Subject: [PATCH 7/9] never meant to touch this file --- modules/node/init.zsh | 2 -- 1 file changed, 2 deletions(-) diff --git a/modules/node/init.zsh b/modules/node/init.zsh index 62d434dcc6..904d24d931 100644 --- a/modules/node/init.zsh +++ b/modules/node/init.zsh @@ -16,8 +16,6 @@ if (( ! $+commands[node] )); then return 1 fi -pmodload 'helper' - # Load NPM completion. if (( $+commands[npm] )); then cache_file="${0:h}/cache.zsh" From f4965eeac235bdb73d2d0cacc2126f15a43198d4 Mon Sep 17 00:00:00 2001 From: Alex Reece Date: Fri, 14 Jun 2013 20:00:09 -0400 Subject: [PATCH 8/9] Get foreground window 30% faster Thanks micampe! --- modules/notify/functions/focused_window_id | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/modules/notify/functions/focused_window_id b/modules/notify/functions/focused_window_id index e7c63e2f75..1377a69f9b 100644 --- a/modules/notify/functions/focused_window_id +++ b/modules/notify/functions/focused_window_id @@ -6,12 +6,8 @@ case "$OSTYPE" in (darwin*) - osascript -e 'tell application "System Events" to ¬' \ - -e ' set focus_app_name to ¬' \ - -e ' name of first application process ¬' \ - -e ' whose frontmost is true' \ - -e 'tell application focus_app_name to ¬' \ - -e ' get id of front window' + osascript -e 'tell application (path to frontmost application as text) ¬' \ + -e ' to get id of front window' ;; (linux-gnu*) # http://stackoverflow.com/a/8688624/447288 From 5e5ae8c0fd956931911390e584c497e1df5855ec Mon Sep 17 00:00:00 2001 From: Alex Reece Date: Sat, 15 Jun 2013 13:51:06 -0400 Subject: [PATCH 9/9] no error text --- modules/notify/functions/focused_window_id | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/notify/functions/focused_window_id b/modules/notify/functions/focused_window_id index 1377a69f9b..bd46a2d1e2 100644 --- a/modules/notify/functions/focused_window_id +++ b/modules/notify/functions/focused_window_id @@ -7,7 +7,7 @@ case "$OSTYPE" in (darwin*) osascript -e 'tell application (path to frontmost application as text) ¬' \ - -e ' to get id of front window' + -e ' to get id of front window' 2>/dev/null ;; (linux-gnu*) # http://stackoverflow.com/a/8688624/447288