Skip to content

Commit

Permalink
feat!: add long breaks and pausing/resuming
Browse files Browse the repository at this point in the history
  • Loading branch information
olimorris authored Aug 11, 2023
1 parent 3e9239a commit 6084d22
Show file tree
Hide file tree
Showing 7 changed files with 504 additions and 261 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
*.txt
todo.md
4 changes: 2 additions & 2 deletions LICENSE.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Copyright (C) 2021 Oli Morris
Copyright (C) 2023 Oli Morris

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the "Software"),
Expand All @@ -16,4 +16,4 @@ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
98 changes: 49 additions & 49 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,16 @@
</p>

<p align="center">
Incorporate the <a href="https://en.wikipedia.org/wiki/Pomodoro_Technique">Pomodoro technique</a> into your <a href="https://github.com/tmux/tmux">tmux</a> setup. Forked from <a href="https://github.com/alexanderjeurissen/tmux-pomodoro">Tmux Pomodoro</a>
Incorporate the <a href="https://en.wikipedia.org/wiki/Pomodoro_Technique">Pomodoro technique</a> into your <a href="https://github.com/tmux/tmux">tmux</a> setup. Forked from <a href="https://github.com/alexanderjeurissen/tmux-pomodoro">Tmux Pomodoro</a><br><br>Please subscribe to <a href="https://github.com/olimorris/tmux-pomodoro-plus/issues/29">this issue</a> to be notifed of any breaking changes to the plugin
</p>

## :sparkles: Features

- Toggle pomodoro timer on/off and see the countdown in the status bar
- Upon completion of a pomodoro, see a break countdown in the status bar
- Desktop alerts for pomodoro and break completion (macOS and Linux only)
- Customise the pomodoro duration and break times
- Automatically repeat your pomodoros
- Toggle a Pomodoro and see the countdown and the break in the status bar
- Skip, pause and resume a Pomodoro/break at any point
- Customise the Pomodoro duration, break times and intervals
- Restart your Pomodoros to automatically or be prompted
- Desktop alerts for Pomodoros and breaks (macOS and Linux only)
- Custom keybindings

## :camera: Screenshots
Expand All @@ -46,22 +46,21 @@ Pomodoro timer menu:
set -g @plugin 'olimorris/tmux-pomodoro-plus'
```

> **Note:** The above line should be _before_ `run '~/.tmux/plugins/tpm/tpm'`
> **Note**: The above line should be _before_ `run '~/.tmux/plugins/tpm/tpm'`
2. Then press `tmux-prefix` + <kbd>I</kbd> (capital i, as in **I**nstall) to fetch the plugin as per the TPM installation instructions

## :rocket: Usage

### Default keybindings

> **Note:** It's possible to bind start and cancel to the same key!
- `<tmux-prefix> p` to toggle between starting/pausing a Pomodoro/break
- `<tmux-prefix> P` to cancel a Pomodoro/break
- `<tmux-prefix> _` to skip a Pomodoro/break
- `<tmux-prefix> C-p` to open the Pomodoro timer menu
- `<tmux-prefix> M-p` to set a custom Pomodoro timer

- `<tmux-prefix> p` to start a pomodoro/break
- `<tmux-prefix> P` to cancel a pomodoro
- `<tmux-prefix> C-p` to open the pomodoro timer menu
- `<tmux-prefix> M-p` to set a custom pomodoro timer

The pomodoro timer menu and custom pomodoro input are always `<ctrl>/<alt> + [your start pomodoro key]`.
The Pomodoro timer menu and custom Pomodoro input are always `<ctrl>/<alt> + [your start Pomodoro key]`.

### Status bar

Expand All @@ -73,60 +72,61 @@ set -g status-right "#{pomodoro_status}"

## :wrench: Configuration

> **Note:** On Linux, notifications depend on `notify-send/libnotify-bin`
> **Note**: On Linux, notifications depend on `notify-send/libnotify-bin`
The default configuration:

```bash
set -g @pomodoro_start 'p' # Start a Pomodoro or start break with tmux-prefix + p
set -g @pomodoro_cancel 'P' # Cancel a Pomodoro with tmux-prefix key + P

set -g @pomodoro_mins 25 # The duration of the pomodoro
set -g @pomodoro_break_mins 5 # The duration of the break after the pomodoro
set -g @pomodoro_repeat false # Auto-repeat the pomodoro? False by default
set -g @pomodoro_auto_start_break true # Auto-start break when pomodoro end? True by default

set -g @pomodoro_on " 🍅" # The formatted output when the pomodoro is running
set -g @pomodoro_ask_break " 🕤 break?" # The formatted output when wait to start break
set -g @pomodoro_complete "" # The formatted output when the break is running
set -g @pomodoro_toggle 'p' # Start/pause a Pomodoro/break
set -g @pomodoro_cancel 'P' # Cancel the current session
set -g @pomodoro_skip '_' # Skip a Pomodoro/break

set -g @pomodoro_mins 25 # The duration of the Pomodoro
set -g @pomodoro_break_mins 5 # The duration of the break after the Pomodoro completes
set -g @pomodoro_intervals 4 # The number of intervals before a longer break is started
set -g @pomodoro_long_break_mins 25 # The duration of the long break
set -g @pomodoro_repeat 'off' # Automatically repeat the Pomodoros?

set -g @pomodoro_on " 🍅" # The formatted output when the Pomodoro is running
set -g @pomodoro_complete " ✔︎" # The formatted output when the break is running
set -g @pomodoro_pause=" ⏸︎" # The formatted output when the Pomodoro/break is paused
set -g @pomodoro_prompt_break " ⏲︎ break?" # The formatted output when waiting to start a break
set -g @pomodoro_prompt_pomodoro " ⏱︎ start?" # The formatted output when waiting to start a Pomodoro

set -g @pomodoro_menu_position "R" # The location of the menu releative to the screen
set -g @pomodoro_sound 'off' # Sound for desktop notifications (Run `ls /System/Library/Sounds` for a list of sounds to use on Mac)
set -g @pomodoro_notifications 'off' # Enable desktop notifications from your terminal
set -g @pomodoro_granularity 'off' # Enables MM:SS (ex: 00:10) format instead of the default (ex: 1m)
```

set -g @pomodoro_notifications 'off' # Enable desktop notifications from your terminal
set -g @pomodoro_sound 'off' # Sound for desktop notifications (Run `ls /System/Library/Sounds` for a list of sounds to use on Mac)
### Using the menu

set -g @pomodoro_granularity 'off' # Enables MM:SS (ex: 00:10) format instead of the default (ex: 1m)
```
It's possible to configure the timings from built-in menus within the app:

### Customising the status line

The output from the plugin can be completely customised to fit in with your status line. For example:
The output from the plugin can be customised to fit in with your statusline:

```bash
set -g @pomodoro_on "#[fg=$text_red]🍅 "
set -g @pomodoro_complete "#[fg=$text_green]🍅 "
set -g @pomodoro_ask_break "#[fg=$color_gray]🕤 ? "
set -g @pomodoro_pause "#[fg=$color_yellow]🍅 "
set -g @pomodoro_prompt_break "#[fg=$color_green]🕤 ? "
set -g @pomodoro_prompt_pomodoro "#[fg=$color_gray]🕤 ? "
```

A real-time countdown can also be enabled in the status line:
The current and total number of intervals can be displayed:

```bash
set -g @pomodoro_granularity 'on'
set -g status-interval 1 # Refresh the status line every second
set -g @pomodoro_show_intervals "#[fg=$color_gray][%s/%s]"
```

## :microscope: How it works

- Starting a Pomodoro:
- Uses `date +%s` to get the current timestamp and write to `/tmp/pomodoro.txt`
- This allows the app to keep track of the elapsed time
- Completing a Pomodoro:
- Writes the status of the pomodoro to `/tmp/pomodoro_status.txt`
- This allows the app to know what type of notification to send
- Cancelling a Pomodoro:
- Deletes `/tmp/pomodoro.txt`
- Deletes `/tmp/pomodoro_status.txt`
- Getting the status of a Pomodoro:
- Countdown: Compares current timestamp (via `date +%s`) with the start timestamp in `/tmp/pomodoro.txt`
- Break: Compares the current timestamp with the start timestamp and adds on the break duration
A real-time countdown can be also be displayed:

```bash
set -g @pomodoro_granularity 'on'
set -g status-interval 1 # Refresh the status line every second
```

## :clap: Credits

Expand Down
67 changes: 40 additions & 27 deletions pomodoro.tmux
Original file line number Diff line number Diff line change
@@ -1,52 +1,68 @@
#!/usr/bin/env bash
# ______________________________________________________________| locals |__ ;
# _______________________________________________________________| locals |__ ;

CURRENT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
POMODORO_MINS_FILE="$CURRENT_DIR/scripts/user_mins.txt"
POMODORO_BREAK_MINS_FILE="$CURRENT_DIR/scripts/user_break_mins.txt"

default_start_pomodoro="p"
start_pomodoro="@pomodoro_start"
POMODORO_USER_MINS_FILE="$CURRENT_DIR/scripts/user_mins.txt"
POMODORO_USER_INTERVAL_FILE="$CURRENT_DIR/scripts/user_interval.txt"
POMODORO_USER_BREAK_MINS_FILE="$CURRENT_DIR/scripts/user_break_mins.txt"
POMODORO_USER_LONG_BREAK_MINS_FILE="$CURRENT_DIR/scripts/user_long_break_mins.txt"

default_toggle_pomodoro="p"
toggle_pomodoro="@pomodoro_toggle"
default_skip_pomodoro="_"
skip_pomodoro="@pomodoro_skip"
default_cancel_pomodoro="P"
cancel_pomodoro="@pomodoro_cancel"

pomodoro_status="#($CURRENT_DIR/scripts/pomodoro.sh)"
pomodoro_status_interpolation_string="\#{pomodoro_status}"

# _____________________________________________________________| methods |__ ;
# ______________________________________________________________| methods |__ ;

source "$CURRENT_DIR/scripts/helpers.sh"

sync_timers() {
load_custom_timings() {
pomodoro_mins_exists=$(tmux show-option -gqv "@pomodoro_mins")
export pomodoro_mins_exists

if [ "$pomodoro_mins_exists" != "" ]; then
remove_file "$POMODORO_MINS_FILE"
remove_file "$POMODORO_BREAK_MINS_FILE"
remove_file "$POMODORO_USER_MINS_FILE"
remove_file "$POMODORO_USER_INTERVAL_FILE"
remove_file "$POMODORO_USER_BREAK_MINS_FILE"
remove_file "$POMODORO_USER_LONG_BREAK_MINS_FILE"
return 0
fi

elif [ -f "$POMODORO_MINS_FILE" ] &&
[ -f "$POMODORO_BREAK_MINS_FILE" ]; then
set_tmux_option "@pomodoro_mins $(read_file "$POMODORO_MINS_FILE")"
set_tmux_option "@pomodoro_break_mins $(read_file "$POMODORO_BREAK_MINS_FILE")"
if file_exists "$POMODORO_USER_MINS_FILE"; then
set_tmux_option "@pomodoro_mins $(read_file "$POMODORO_USER_MINS_FILE")"
fi
if file_exists "$POMODORO_USER_INTERVAL_FILE"; then
set_tmux_option "@pomodoro_intervals $(read_file "$POMODORO_USER_INTERVAL_FILE")"
fi
if file_exists "$POMODORO_USER_BREAK_MINS_FILE"; then
set_tmux_option "@pomodoro_break_mins $(read_file "$POMODORO_USER_BREAK_MINS_FILE")"
fi
if file_exists "$POMODORO_USER_LONG_BREAK_MINS_FILE"; then
set_tmux_option "@pomodoro_long_break_mins $(read_file "$POMODORO_USER_LONG_BREAK_MINS_FILE")"
fi
}

set_bindings() {
start_binding=$(get_tmux_option "$start_pomodoro" "$default_start_pomodoro")
export start_binding

for key in $start_binding; do
set_keybindings() {
toggle_binding=$(get_tmux_option "$toggle_pomodoro" "$default_toggle_pomodoro")
for key in $toggle_binding; do
tmux bind-key "$key" run-shell "$CURRENT_DIR/scripts/pomodoro.sh toggle"
tmux bind-key "C-$key" run-shell "$CURRENT_DIR/scripts/pomodoro.sh menu"
tmux bind-key "M-$key" run-shell "$CURRENT_DIR/scripts/pomodoro.sh custom"
done

cancel_binding=$(get_tmux_option "$cancel_pomodoro" "$default_cancel_pomodoro")
export cancel_binding
skip_binding=$(get_tmux_option "$skip_pomodoro" "$default_skip_pomodoro")
for key in $skip_binding; do
tmux bind-key "$key" run-shell "$CURRENT_DIR/scripts/pomodoro.sh skip"
done

cancel_binding=$(get_tmux_option "$cancel_pomodoro" "$default_cancel_pomodoro")
for key in $cancel_binding; do
tmux bind-key "$key" run-shell "$CURRENT_DIR/scripts/pomodoro.sh toggle"
tmux bind-key "$key" run-shell "$CURRENT_DIR/scripts/pomodoro.sh cancel"
done
}

Expand All @@ -60,17 +76,14 @@ update_tmux_option() {
local option="$1"

option_value="$(get_tmux_option "$option")"
export option_value

new_option_value="$(do_interpolation "$option_value")"
export new_option_value

set_tmux_option "$option" "$new_option_value"
}

main() {
sync_timers
set_bindings
load_custom_timings
set_keybindings
update_tmux_option "status-right"
update_tmux_option "status-left"
}
Expand Down
59 changes: 48 additions & 11 deletions scripts/helpers.sh
Original file line number Diff line number Diff line change
Expand Up @@ -23,41 +23,78 @@ set_tmux_option() {
file_exists() {
local file="$1"
if [ -f "$file" ]; then
echo 0 # file exists
else
echo 1 # file does not exist
return 0 # file exists
fi

return 1 # file does not exist
}

read_file() {
local file=$1
local file="$1"
if [ -f "$file" ]; then
cat "$file"
else
echo -1
echo 1
fi
}

remove_file() {
local file=$1
local file="$1"
if [ -f "$file" ]; then
rm "$file"
fi
}

write_to_file() {
local data=$1
local file=$2
local data="$1"
local file="$2"
echo "$data" >"$file"
}

if_inside_tmux() {
test -n "${TMUX}"
}

refresh_statusline() {
if_inside_tmux && tmux refresh-client -S
}

minutes_to_seconds() {
local minutes=$1
echo $((minutes * 60))
}

send_notification() {
if [ "$(get_notifications)" == 'on' ]; then
local title=$1
local message=$2
sound=$(get_sound)
export sound
case "$OSTYPE" in
linux* | *bsd*)
notify-send -t 8000 "$title" "$message"
if [[ "$sound" == "on" ]]; then
beep -D 1500
fi
;;
darwin*)
if [[ "$sound" == "off" ]]; then
osascript -e 'display notification "'"$message"'" with title "'"$title"'"'
else
osascript -e 'display notification "'"$message"'" with title "'"$title"'" sound name "'"$sound"'"'
fi
;;
esac
fi
}

debug_log() {
# add log print into the code (debug_log "hello from tmux_pomodoro_plus)"
# set true to enable log messages
# follow the log using "tail -f /tmp/tmux_pomodoro_debug_log/log.txt"
# follow the log using "tail -f /tmp/pomodoro/pomodoro.log"
if true; then
DIR="/tmp/tmux_pomodoro_debug_log/"
FILE="log.txt"
DIR="/tmp/pomodoro"
FILE="pomodoro.log"
mkdir -p $DIR
echo "$(date +%T) " "$1" >>"$DIR/$FILE"
fi
Expand Down
Loading

0 comments on commit 6084d22

Please sign in to comment.