Skip to content

Instantly share code, notes, and snippets.

@huytd
Last active May 23, 2023 05:35
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save huytd/0cc4063577771f38dae92666b8f50231 to your computer and use it in GitHub Desktop.
Save huytd/0cc4063577771f38dae92666b8f50231 to your computer and use it in GitHub Desktop.
A pomodoro timer that write the tracked time into a file near you
#!/usr/bin/env python3
##############################################################################
# Installation:
# First, run the following command to install the required dependencies:
# pip3 install rumps
# Then, copy the script to /usr/bin/local/tmr
##############################################################################
import rumps
import sys
import os
from datetime import datetime, timedelta
import re
DATE_TIME_FORMAT = '%Y-%m-%d %H:%M:%S'
currentLogFilePath = os.getcwd() + '/tasks.log'
param = ''.join(sys.argv[1:2])
currentTask = ' '.join(sys.argv[2:]).strip().replace(',', '')
startTime = datetime.now().strftime(DATE_TIME_FORMAT)
duration = 25 * 60
if re.match(r'^report$', param):
reportDay = datetime.today()
if len(sys.argv) > 2:
dateDiff = int(re.findall(r'\d+', sys.argv[2])[0])
reportDay = reportDay - timedelta(days=dateDiff)
print("🗓️ " + reportDay.strftime('%b %d, %Y') + "\n" + "-" * 15 + "\n")
with open(currentLogFilePath, 'r') as f:
for line in f.readlines():
cols = line.strip().split(',')
startTime = datetime.strptime(cols[0], DATE_TIME_FORMAT)
endTime = datetime.strptime(cols[1], DATE_TIME_FORMAT)
currentTask = cols[2]
duration = int(int(cols[3]) / 60)
# check if startTime is within today date or not
if startTime.date() == reportDay.date():
print("☑️ {} - {} / {} min\n {}\n".format(startTime.strftime("%H:%M:%S"), endTime.strftime("%H:%M:%S"), duration, currentTask))
sys.exit()
elif re.match(r'\d+m$', param):
duration = int(re.findall(r'\d+', param)[0]) * 60
else:
currentTask = param + ' ' + currentTask
print("Working on task: {}\nDuration: {} min".format(currentTask, duration/60))
class TmrApp(object):
def __init__(self):
self.app = rumps.App("Timer", "🍅")
self.timer = rumps.Timer(self.on_tick, 1)
self.timer.count = 0
self.timer.end = duration
self.timer.start()
def run(self):
self.app.run()
def on_tick(self, sender):
time_left = sender.end - sender.count
mins = time_left // 60 if time_left >= 0 else time_left // 60 + 1
secs = time_left % 60 if time_left >= 0 else (-1 * time_left) % 60
if mins == 0 and time_left < 0:
rumps.notification(title="Time up!", subtitle="Well done! It's time for some break!", message='')
self.timer.stop()
self.record_task()
print("☕ Well done!")
rumps.quit_application()
else:
self.app.title = '🍅 {:2d}:{:02d}'.format(mins, secs)
sender.count += 1
def record_task(self):
endTime = datetime.now().strftime(DATE_TIME_FORMAT)
with open(currentLogFilePath, 'a') as f:
f.write('{},{},{},{}\n'.format(startTime,endTime,currentTask,duration))
if __name__ == '__main__':
app = TmrApp()
app.run()
@huytd
Copy link
Author

huytd commented May 17, 2023

Screenshot

image

image

Install

cp pomodoro.py /usr/local/bin/pomo
chmod +x /usr/local/bin/pomo

Usage

# run a default 25 min timer with a task description
$ pomo This is my task

# run a default 25 min timer without task description
$ pomo

# run a 3 min timer 
$ pomo 3m

# run a 5 min timer with task description
$ pomo 5m Hello, this is a task description

After the timer finished, the task log will be written in the tasks.log file in the current directory in the following format:

<start-time>,<end-time>,<task-description>,<duration>

If needed, you can parse the tasks.log file just like a CSV file.

Tips & tricks

  1. Run the timer with & disown in the end will detatch the process from the current terminal.
  2. Script to run via Raycast
#!/bin/bash

# Required parameters:
# @raycast.schemaVersion 1
# @raycast.title Run Pomodoro Timer
# @raycast.mode silent

# Optional parameters:
# @raycast.icon ⏰
# @raycast.argument1 { "type": "text", "placeholder": "For how long?" }
# @raycast.argument2 { "type": "text", "placeholder": "Task description" }

# Documentation:
# @raycast.description Run a pomodoro timer
# @raycast.author Huy Tran

cd $HOME && pomo $1 $2

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment