Compare commits

...

10 Commits

5 changed files with 227 additions and 0 deletions

5
.gitignore vendored
View File

@ -18,3 +18,8 @@
__pycache__ __pycache__
**.ipynb_checkpoints **.ipynb_checkpoints
# Added by cargo
/target

12
install Executable file
View File

@ -0,0 +1,12 @@
#! /bin/sh
#
# install.sh
# Copyright (C) 2023 gum <gum@gumvy>
#
# Distributed under terms of the MIT license.
#
python -m venv --prompt break-timer .venv
. .venv/bin/activate
pip install -r requirements.txt

20
makefile Normal file
View File

@ -0,0 +1,20 @@
pwd = $(shell pwd)
name = $(notdir $(pwd))
symlink = ${HOME}/.local/bin/break-timer
venv = $(pwd)/.venv/bin/python
$(symlink): $(venv)
echo "#!/bin/sh\n$(venv) $(pwd)/src/main.py \"\$$@\"" > $(symlink)
chmod +x $(symlink)
$(venv): requirements.txt
python -m venv --prompt $(name) .venv
. .venv/bin/activate; \
pip install --upgrade pip; \
pip install -r requirements.txt
clean:
rm -r .venv
rm $(symlink)

1
requirements.txt Normal file
View File

@ -0,0 +1 @@
pyright

189
src/main.py Executable file
View File

@ -0,0 +1,189 @@
#! /home/gum/p/break/.venv/bin/python
# vim:fenc=utf-8
#
# Copyright © 2023 gum <gum@gums-lappy>
#
# Distributed under terms of the MIT license.
"""
Play my playlist every few minutes.
"""
import os
import sys
import threading
from argparse import ArgumentParser
from datetime import datetime
from select import select
from subprocess import DEVNULL, Popen, run
from termios import TCIOFLUSH, tcflush
from time import sleep, time
WINDOW_TITLE = ""
def generate_interval(work_time: int, break_time: int):
"""
Generate the interval between plays in seconds.
"""
if work_time and break_time:
while True:
yield work_time
yield break_time
else:
# pomodoro scheme
while True:
yield 60 * 25
for _ in range(3):
yield 60 * 5
yield 60 * 25
yield 60 * 30
def play_playlist(playlist):
"""
Play the playlist.
"""
return Popen(
["mpv", "--shuffle", "--no-video", playlist], stdout=DEVNULL, stderr=DEVNULL
)
def test_playlist(playlist, duration=None):
print(
"testing playlist, press enter to start if you hear the playlist",
end="",
flush=True,
)
if duration is None:
duration = float("inf")
play = play_playlist(playlist)
focus=bool(WINDOW_TITLE) and duration is None
wait_or_enter(duration, i3_focus=focus)
play.terminate()
def wait_or_enter(duration, i3_focus=False):
"""
A timer that will stop if the user presses enter.
The i3_focus flag will focus the i3 window with the title "break" to prevent the user from doing other things while the timer lasts.
"""
stop = ""
start = time()
if i3_focus:
run(
["i3-msg", f'[title="{WINDOW_TITLE}"] focus, fullscreen'],
stdout=DEVNULL,
stderr=DEVNULL,
)
while not stop and (time() - start < duration): # Run until flag is True
if i3_focus:
run(
["i3-msg", f'[title="{WINDOW_TITLE}"] focus'],
stdout=DEVNULL,
stderr=DEVNULL,
)
stop, _, _ = select([sys.stdin], [], [], 1)
if i3_focus:
run(
["i3-msg", f'[title="{WINDOW_TITLE}"] move to scratchpad'],
stdout=DEVNULL,
stderr=DEVNULL,
)
if time() - start < duration:
return sys.stdin.readline().strip()
else:
tcflush(sys.stdin, TCIOFLUSH)
print(flush=True)
return
def write_break_message(msg):
today = datetime.now().strftime("%Y-%m-%d")
minute = datetime.now().strftime("%H:%M")
msg = f"{minute} BREAK {msg}"
with open(f"/home/gum/z/break/{today}.txt", "a") as f:
print(msg)
f.write(msg + "\n")
def main(playlist, work_time, break_time):
interval = generate_interval(work_time, break_time)
while True:
# work
i = next(interval)
print("work for", i // 60, "minutes", end="", flush=True)
wait_or_enter(i)
# break
i = next(interval)
print("break for", i // 60, "minutes", end=" ", flush=True)
msg = wait_or_enter(i, i3_focus=bool(WINDOW_TITLE))
# start music to signal the end of a break.
if not msg:
print("> ", end="", flush=True)
play = play_playlist(playlist)
msg = wait_or_enter(float("inf"), i3_focus=bool(WINDOW_TITLE))
play.terminate()
write_break_message(msg)
def timer(playlist, duration):
second = datetime.now().strftime("%H:%M:%S")
print(second, "wait for", duration, "seconds")
msg = wait_or_enter(duration, i3_focus=bool(WINDOW_TITLE))
# start music to signal the end of a break.
if msg is None:
print("timer is over, press enter to quit", end="", flush=True)
play = play_playlist(playlist)
wait_or_enter(float("inf"), i3_focus=bool(WINDOW_TITLE))
play.terminate()
if __name__ == "__main__":
parser = ArgumentParser()
parser.add_argument(
"--playlist",
default=os.path.expanduser('~') + "/m",
help="path to the folder with the playlist to play",
)
parser.add_argument(
"--work-time",
default=None,
type=int,
help="Interval between plays in minutes, if empty I use the pomodoro scheme.",
)
parser.add_argument(
"--break-time",
default=None,
type=int,
help="Interval between plays in minutes, if empty I use the pomodoro scheme.",
)
parser.add_argument(
"--window-title",
default=None,
type=str,
help="window title of this program, to prevent the user from doing other things during a break.",
)
parser.add_argument(
"--once",
default=None,
type=int,
help="set true for this to be a single timer",
)
parser.add_argument(
"--test-sound",
action="store_true",
help="test the sound before starting the timer",
)
args = parser.parse_args()
WINDOW_TITLE = args.window_title
if args.test_sound:
test_playlist(args.playlist)
elif args.once is None:
# For some reason the first time I play the playlist it doesn't work.
# This is a workaround.
test_playlist(args.playlist, 10)
if args.once:
timer(args.playlist, args.once)
else:
main(args.playlist, args.work_time, args.break_time)