benjamin melançon
0d39fb9e30
File pomodoroprompt.py, line 56, in log_step timelog_file = Path(prepare_file(utc_start, ext='log', daily=True)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File pomodoroprompt.py, line 100, in prepare_file logpath_tz = timezone('US/Pacific') ^^^^^^^^^^^^^^^^^^^^^^ pytz.exceptions.UnknownTimeZoneError: 'US/Pacific' Like i'm pretty sure it's right there on the coast but if calling it Los Angeles sooths you cool.
160 lines
5.7 KiB
Python
160 lines
5.7 KiB
Python
import sys
|
|
import csv
|
|
import os
|
|
# This is a local script are we supposed to indicate that?
|
|
import prompt_window
|
|
import time
|
|
from datetime import datetime, timedelta
|
|
from pathlib import Path
|
|
from pytz import timezone
|
|
|
|
import pytz
|
|
|
|
WORK_MIN = 25 # Minutes for a work session
|
|
SHORT_MIN = 5 # Minutes for a short break
|
|
LONG_MIN = 15 # Minutes for a long break (NOT YET IMPLEMENTED)
|
|
INTERRUPTED_MIN = 1 # Minimum minutes to ask to record an interrupted Pomodoro
|
|
QUIET = True
|
|
|
|
def pomodoro_prompt_plan(whatdid = ''):
|
|
""" Ask about what task will be worked on (showing last thing worked on)
|
|
"""
|
|
text = "What're you gonna do?"
|
|
# NOTE: If we can do system notifications that when clicked will focus the terminal
|
|
# running pomodoro prompt, that might be even better than the pop-up GUI text entry.
|
|
whatnext = prompt_window.prompt(prompt=text, task=whatdid)
|
|
# Pressing cancel returns None, but we want to just treat it as an empty string.
|
|
if whatnext is None:
|
|
whatnext = ''
|
|
return whatnext
|
|
|
|
def pomodoro_prompt_report(whatnext):
|
|
""" Ask what task was completed, showing the last task claimed to be being worked on
|
|
"""
|
|
text = "What'd you do?"
|
|
whatdid = prompt_window.prompt(prompt=text, task=whatnext)
|
|
# Pressing cancel returns None, but we want to just treat it as an empty string.
|
|
if whatdid is None:
|
|
whatdid = ''
|
|
return whatdid
|
|
|
|
def quit_prompt():
|
|
""" Confirm exit or start a new pomodoro
|
|
"""
|
|
print('\nPress p to start a new pomodoro, q to quit')
|
|
choice = input('p/q: ').strip().lower()
|
|
if choice in ('p', 'pomodoro'):
|
|
return
|
|
elif choice in ('q', 'quit', 'exit'):
|
|
sys.exit(0)
|
|
else:
|
|
quit_prompt()
|
|
|
|
def log_step(text, utc_start, end_section=False):
|
|
""" Write detailed log of all events
|
|
"""
|
|
timelog_file = Path(prepare_file(utc_start, ext='log', daily=True))
|
|
timelog_file.touch(exist_ok=True)
|
|
with timelog_file.open('a') as timelog:
|
|
timelog.write(text + '\n')
|
|
if end_section:
|
|
timelog.write('\n\n')
|
|
|
|
def record_task(whatnext, whatdid, start, end=None):
|
|
""" Record completed pomodoro to CSV
|
|
"""
|
|
if end is None:
|
|
end = datetime.now(pytz.utc)
|
|
|
|
filepath = prepare_file(start)
|
|
if not os.path.isfile(filepath):
|
|
with open(filepath, 'w', newline='') as csvfile:
|
|
log = csv.writer(csvfile)
|
|
log.writerow(['started', 'recorded', 'description', 'intention'])
|
|
|
|
with open(filepath, 'a', newline='') as csvfile:
|
|
log = csv.writer(csvfile)
|
|
log.writerow([start, end, whatdid, whatnext])
|
|
|
|
def str_minutes(time_diff):
|
|
""" Return at least whole seconds from a time difference
|
|
"""
|
|
return str(time_diff).split('.')[0]
|
|
|
|
def countdown_to(until):
|
|
""" Display a timer counting down to until
|
|
"""
|
|
while datetime.now(pytz.utc) <= until:
|
|
to_go = until-datetime.now(pytz.utc)
|
|
print('\r', str_minutes(to_go), sep='', end='')
|
|
time.sleep(1)
|
|
|
|
def prepare_file(utc_start, ext='csv', daily=False):
|
|
# Save timelogs relative to script directory (NOT from where called)
|
|
logpath = os.path.dirname(os.path.realpath(__file__)) + '/log'
|
|
# Ensure log directory exists.
|
|
if not os.path.exists(logpath):
|
|
os.makedirs(logpath)
|
|
# We consider 3am the switchover to a new day, so we skip extra math
|
|
# and use Pacific time to get three hours later than our Eastern time.
|
|
logpath_tz = timezone('America/Los_Angeles')
|
|
logpath_date = utc_start.astimezone(logpath_tz)
|
|
timelog_path = logpath + '/' + str(logpath_date.year);
|
|
if (daily):
|
|
timelog_path += '-' \
|
|
+ format(logpath_date.month, '02') + '-' \
|
|
+ format(logpath_date.day, '02')
|
|
timelog_path += '.' + ext
|
|
return timelog_path
|
|
|
|
def main():
|
|
whatdid = ''
|
|
while True:
|
|
whatnext = pomodoro_prompt_plan(whatdid)
|
|
|
|
start = datetime.now(pytz.utc)
|
|
end = start + timedelta(minutes=WORK_MIN)
|
|
log_step('Start with plan: ' + whatnext, start)
|
|
try:
|
|
print('Working on: ' + whatnext)
|
|
countdown_to(end)
|
|
if not QUIET:
|
|
from playsound import playsound
|
|
playsound('res/timesup.aac')
|
|
whatdid = pomodoro_prompt_report(whatnext)
|
|
record_task(whatnext, whatdid, start)
|
|
log_step('Completed pomodoro: ' + whatdid, start, True)
|
|
print('\nWorked on: ' + whatdid)
|
|
|
|
print('Break time!')
|
|
# We're taking a break. Clear out task start/end times.
|
|
start = None
|
|
end = datetime.now(pytz.utc) + timedelta(minutes=SHORT_MIN)
|
|
countdown_to(end)
|
|
if not QUIET:
|
|
playsound('res/timesup.aac')
|
|
continue
|
|
except KeyboardInterrupt:
|
|
if start is None:
|
|
quit_prompt()
|
|
continue
|
|
time_spent = datetime.now(pytz.utc) - start
|
|
if time_spent < timedelta(minutes=INTERRUPTED_MIN):
|
|
quit_prompt()
|
|
continue
|
|
time_spent_str = str_minutes(time_spent)
|
|
print('\n{} time spent, save?'.format(time_spent_str))
|
|
choice = input('[y]/n: ').strip()
|
|
if choice.lower() in ('y', 'yes', ''):
|
|
whatdid = pomodoro_prompt_report(whatnext)
|
|
record_task(whatnext, whatdid, start)
|
|
log_step('Incomplete (' + time_spent_str + ') pomodoro: ' + whatdid, start, True)
|
|
quit_prompt()
|
|
else:
|
|
print('What did you break?')
|
|
# If we somehow end up here, try a last-ditch effort to save.
|
|
record_task(whatnext, 'Incomplete, interrupted task:' + whatnext, start)
|
|
log_step('Incomplete, interrupted task:' + whatnext, start, True)
|
|
|
|
if __name__ == '__main__':
|
|
main()
|