Skip to content

Instantly share code, notes, and snippets.

@petethepig

petethepig/README.md Secret

Last active Jul 25, 2021
Embed
What would you like to do?
Alert yourself after a long-running task in terminal

Alert yourself after a long-running task in terminal

For the last few months I've been working on pyroscope, I’ve often found myself getting distracted when I run any long tasks in the terminal (tests / docker builds).

This little snippet helps me get back to what I was doing in the terminal by alerting me via a sound message and also a macOS notification.

demo

Instructions

Step 1. Install terminal-notifier:

brew install terminal-notifier

Step 2. Add the following code to .bash_profile:

# Open ~/.bash_profile and add these functions:

function timer_start {
  timer=${timer:-$SECONDS}
}

# this makes bash run timer_start every time you run a command
trap 'timer_start' DEBUG

function notify_when_done {
  timer_show=$(($SECONDS - $timer))
  unset timer
  # 10 is the notification threshold in seconds
  if (( ${timer_show} > 10 )); then
    # modify this section to fit your needs:
    say "Done with task"
    terminal-notifier -title "Terminal" -message "Done with task! Exit status: $? Time: ${timer_show}s"
  fi
}

# this makes bash run notify_when_done command after every command
if [ "$PROMPT_COMMAND" == "" ]; then
  PROMPT_COMMAND="notify_when_done"
else
  PROMPT_COMMAND="$PROMPT_COMMAND; notify_when_done"
fi

Update: for information on how to set this up on Linux or with other shells (fish / zsh) see Hacker News comments.

@l0b0

This comment has been minimized.

Copy link

@l0b0 l0b0 commented Feb 25, 2021

Thanks for the tip! My implementation

@gitowiec

This comment has been minimized.

Copy link

@gitowiec gitowiec commented Feb 25, 2021

Thanks for the tip! My implementation

Thanks for the Linux version, it is much more useful for me!

@figbux

This comment has been minimized.

Copy link

@figbux figbux commented Feb 25, 2021

Thanks for the tip! My implementation

How it behaves with vim, manpages etc? They take quite a long time but they shouldn't alert

@c02y

This comment has been minimized.

Copy link

@c02y c02y commented Feb 25, 2021

If anyone is using fish-shell, https://github.com/franciscolourenco/done can be used for the same purpose, works on Windows/macOS/Linux

@l0b0

This comment has been minimized.

Copy link

@l0b0 l0b0 commented Feb 25, 2021

How it behaves with vim, manpages etc? They take quite a long time but they shouldn't alert

@figbux It'll alert for those. I'm not sure what an elegant workaround would look like (is it possible to detect whether the command was interactive or not?), but you could of course do something like this (untested):

if [[ "$(("$SECONDS" - "$__bashrc_command_start"))" -gt 60 ]] \
    && ! grep --fixed-strings --line-regexp --quiet --regexp=man --regexp=vim <<< "$__bashrc_command"
@bertrand-caron

This comment has been minimized.

Copy link

@bertrand-caron bertrand-caron commented Feb 26, 2021

My version for zsh, that excludes long-running commands like vim, etc.:

### Source: https://gist.github.com/petethepig/2d29e8b7e2ebc808bfe760b632608966
function timer_start {
  timer=${timer:-$SECONDS}
}

# this makes bash run timer_start every time you run a command
trap 'timer_start' DEBUG

function notify_when_done {
  timer_show=$(($SECONDS - $timer))
  unset timer
  # 15 is the notification threshold in seconds
  if (( ${timer_show} > 15 )); then
    # modify this section to fit your needs:
    printf \\a
    terminal-notifier -title "Terminal" -message "Done with task $1! Exit status: $? Time: ${timer_show}s"
  fi
}

# export command we are about to run, so we can inject it in the notification once done
preexec() {
	export _CMD=$1
}
# this makes zsh run notify_when_done command after every command
precmd() {
    if ! [[ ${_CMD} =~ '^(v|vim|ssh|gc|gs|gd) ' ]] {
	    notify_when_done ${_CMD}
    }
}
### END
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment