You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

304 lines
8.6 KiB

#!/usr/bin/env zsh
# Here how it is intended to work
# When you start the script, it asks you the name of the task
# Then you work for 25 min.
# Once finished you are notified it is time to take a break (5 min).
# After 4 work sessions, you take a longer break (30 min).
# Each work session require you enter a name.
# At the end of the day, all your tasks are keep into ~/Documents/Pomodoro
POMODORO_NO_LOGS=0
POMODORO_LOG_DIRECTORY="$HOME/Documents/Pomodoro"
# if you add a TODO.txt file in $POMODORO_LOG_DIRECTORY
# The list of TODO is presented for shortcut
POMODORO_TODO_FILE="$POMODORO_LOG_DIRECTORY/TODO.txt"
# times are in minutes
POMODORO_WORKING_TIME=25
POMODORO_SHORT_RELAX_TIME=5
POMODORO_LONG_RELAX_TIME=15
# you can install get-shit-done at
# http://github.com/yogsototh/get-shit-done.git
# If you want to block some popular website
# during your work session.
# note you can overide these functions in $HOME/.pomodoro
has(){
which $1 >/dev/null 2>&1
}
focus_on() {
has get-shit-done && {
sudo =get-shit-done work
print -- "[focus on]"
}
}
focus_off() {
has get-shit-done && {
sudo =get-shit-done play
print -- "[focus off]"
}
}
pomodoro_work_started() { focus_on }
pomodoro_work_time_ended() {}
pomodoro_pause_started() { focus_off }
pomodoro_pause_time_ended() { focus_on }
# used to list latests task names
typeset -U latestTasks
typeset -U todoTasks
showConfMessage() {
print -- "You can use the \$HOME/.pomodoro file to declare your own notification system"
print -- "For example you could add: "
print -- "POMODORO_NOTIFY=\"notify_cmd --message=%m\""
print
print -- "Then notification will be executed as \"notify_cmd\" --message=\"notification message\""
}
# A nofity function as portable as possible
notify() {
local message="$*"
print -n -- "$message"
if [[ "$POMODORO_NOTIFY" != "" ]]; then
eval $( echo $POMODORO_NOTIFY | sed 's/%m/"'$message'"/g' )
return
fi
case $(uname) in
Darwin) # On Mac
if has terminal-notifier; then
# you could install terminal-notifier from brew
terminal-notifier -message "$message" -title "pomodoro"
fi
if has growlnotify; then
growlnotify -m "[Pomodoro] $message"
fi
;;
Linux) # on Ubuntu => sudo apt-get install libnotify-bin
# on other systems libnotify
local DELAY=5 # in seconds
local ICON=/usr/share/icons/Tango/32x32/actions/appointment.png
if has notify-send; then
notify-send \
--urgency=critical \
--expire-time=$(( DELAY * 1000 )) \
--icon=$ICON "[Pomodoro] " $message
fi
;;
*) {
print -- "I didn't made any notification for your system"
showConfMessage
} >&2
esac
}
# show timer take two arguments
# time and a message
# after time is expired the message is send to notification system
# And the counter grow.
function timer() {
local timeToWait=$1
local message="$2"
local triggerCmd="$3"
if pretimer $timeToWait; then
eval $triggerCmd
posttimer $message
fi
}
# Show a timer, stop if you hit Return
function pretimer() {
local m=$1
local s=00
local rem=""
local firsttime=1
while (( m+s > 0 )); do
((s--))
if ((s<0)); then
((s=59))
((m--))
fi
printf "$rem%02d:%02d" $m $s
(( $firsttime )) && {
rem="\b\b\b\b\b"
firsttime=0
}
read -t 1 && {
return 1
}
done
print
return 0
}
# Show a growing counter, stop if you hit Return
funtion posttimer() {
local m=00
local s=00
local rem=""
local firsttime=1
local message="$*"
notify "$message"
while : ; do
((s++))
if ((s>59)); then
((s=0))
((m++))
notify "\r$message "
fi
printf "$rem+%02d:%02d" $m $s
(( $firsttime )) && {
rem="\b\b\b\b\b\b"
firsttime=0
}
read -t 1 && break
done
}
# If you had done some task this week
# We help you find these
function initLatestTasksFromLogFile() {
if [[ ! -r $logfile ]]; then
[[ ! -r $lastweeklogfile ]] && return
latestlogfile="$lastweeklogfile"
else
latestlogfile="$logfile"
fi
local cmd="latestTasks=( $( tail -n 5 $latestlogfile | awk '{printf "\""; gsub(/"/,"\\\""); gsub(/%/,"°/o"); for (i=6;i<=NF;i++) printf $i" "; print "\""}' ) )"
eval $cmd
}
function initTodoTasksFromFile() {
[[ ! -r $POMODORO_TODO_FILE ]] && return
local cmd="todoTasks=( $(< $POMODORO_TODO_FILE | egrep -v '%(wait|done)' | awk '{printf "\""; gsub(/"/,"\\\""); gsub(/%/,"°/o"); printf $0; print "\""; }') )"
eval $cmd
}
# Which file to track your activity?
function initialize() {
# nb is the number of loop we already done
nb=1
# read the .pomodoro file if it exists
[[ -e $HOME/.pomodoro ]] && source $HOME/.pomodoro
if ((POMODORO_NO_LOGS)); then
logfile=/dev/null
else
# Verify where to write podomoro logs
logfiledir="$POMODORO_LOG_DIRECTORY"
logfilename=$(date +"week-%V-%Y.txt")
case $(uname) in
Linux) lastweeklogfile=$(date -d 'last week' +"week-%V-%Y.txt");;
*) lastweeklogfile=$(date -v-7d +"week-%V-%Y.txt");;
esac
logfile=$logfiledir/$logfilename
while [[ ! -d $logfiledir ]]; do
print -- "$logfiledir does not exists. Would you want to create it? (y/n)"
read answer
case $answer in
Y|YES|y|yes) mkdir -p $logfiledir || exit 1;;
*) print -- "Enter a full path of directory to write logs or just enter NO to don't keep tasks."
read answer
case $answer in
N|n|NO|no) logfiledir=/dev; logfile=/dev/null
;;
*) logfiledir=$answer;
NO_LOGS=1;
logfile=$logfiledir/$logfilename ;;
esac
{
print -- "logfiledir=$logfiledir"
(( NO_LOGS )) && print -- "NO_LOGS=1"
} > $HOME/.pomodoro
;;
esac
done
fi
initLatestTasksFromLogFile
initTodoTasksFromFile
}
# ask the title of the tasks
# And present previous tasks and TODO
function askTitle() {
((${#latestTasks})) && print -P -- "%Bworked tasks%b"
local i=1;
print
for task in $latestTasks; do
print -- "$i) $task"
((i++))
done
(( ${#todoTasks} > 0 )) && print -P -- "%BTODO%b"
for task in $todoTasks; do
print -P -- "%B$i) $task%b"
((i++))
done
local choiceMsg=""
((i==2)) && choiceMsg=" (or 1)"
((i>2)) && choiceMsg=" (or 1 - $((i-1)))"
notify "Enter the title of the task${choiceMsg}: "
read task
# if the user returned a number
if print -- $task | grep -e '^[0-9][0-9]*$' >/dev/null; then
# if the number corresond to a latestTasks
if (( task <= ${#latestTasks} )); then
task="${latestTasks[$task]}"
return
fi
# if the number is a todo task number
task=$(( task - ${#latestTasks} ))
if (( task <= ${#todoTasks} )); then
task="${todoTasks[$task]}"
return
fi
fi
# if it wasn't a valid number add the task to latestTasks
latestTasks=( $latestTasks "$task" )
}
# first 3 pauses are short ones
# the 4th is a long one
function compute_pause_time() {
if ((nb++ % 4 == 0)); then
notify "Long pause "
POMODORO_RELAX_TIME=$POMODORO_LONG_RELAX_TIME
else
notify "Relax "
POMODORO_RELAX_TIME=$POMODORO_SHORT_RELAX_TIME
fi
}
# ------------- START -------------
initialize
while (true) {
# Ask the user the title of the task
askTitle
# Start working
startedTime=$(date +"%H:%M")
# notification isn't needed
print -n -- "WORK NOW! "
pomodoro_work_started
timer $POMODORO_WORKING_TIME "Time for a break." pomodoro_work_time_ended
# Task finished
# Write logs
print "$(date +"%A (%F) $startedTime → %H:%M") $task" >> $logfile
# Time for a break
compute_pause_time
pomodoro_pause_started
timer $POMODORO_RELAX_TIME "Time to work!" pomodoro_pause_time_ended
}