this post was submitted on 27 Apr 2026
11 points (76.2% liked)

Programming

26701 readers
340 users here now

Welcome to the main community in programming.dev! Feel free to post anything relating to programming here!

Cross posting is strongly encouraged in the instance. If you feel your post or another person's post makes sense in another community cross post into it.

Hope you enjoy the instance!

Rules

Rules

  • Follow the programming.dev instance rules
  • Keep content related to programming in some way
  • If you're posting long videos try to add in some form of tldr for those who don't want to watch videos

Wormhole

Follow the wormhole through a path of communities !webdev@programming.dev



founded 2 years ago
MODERATORS
 

I was struggling to sit down and start my side projects, so I began reading more about productivity and motivation. Eventually I ended up writing a tiny Pomodoro timer for my terminal — mostly just to help myself get moving.

It’s super minimal: you enter the title, work time, break time, and number of intervals. At the end it generates a simple session report and asks you to write your own conclusion. I like reading my own reports later, so I added that feature.

I also enjoy reading short reports and summaries, so adding them felt natural. And honestly, I prefer building simple tools myself rather than hunting for the “perfect” app.

Works on Windows & Linux, needs only Python.

GitHub: https://github.com/Mietkiewski/MPomidoro
Gumroad PWYW $0+: https://mietkiewski.gumroad.com/l/mpomidoro

top 6 comments
sorted by: hot top controversial new old
[–] three@piefed.social 5 points 8 hours ago (1 children)
import time
import os
import platform
import sys
from datetime import datetime



_old_settings = None
_buffer = ""
YELLOW = "\033[93m"
GREEN = "\033[92m"
RESET = "\033[0m"



def clear_console():
	if platform.system() == "Windows":
		os.system("cls")
	else:
		os.system("clear")

def enable_keyboard_input():
	if sys.platform.startswith("win"):
		pass
	else:
		global _old_settings
		global _termios_imported
		if termios is None:
			import termios
		if _old_settings is not None:
			fd = sys.stdin.fileno()
			termios.tcsetattr(fd, termios.TCSADRAIN, _old_settings)

def disable_keyboard_input():
	if sys.platform.startswith("win"):
		pass
	else:
		global _old_settings
		global _termios_imported
		if termios is None:
			import termios
		fd = sys.stdin.fileno()
		_old_settings = termios.tcgetattr(fd)
		new = termios.tcgetattr(fd)
		new[3] = new[3] & ~termios.ECHO & ~termios.ICANON
		termios.tcsetattr(fd, termios.TCSADRAIN, new)



def input_title(title):
	# enable_keyboard_input()
	in_value = input(title)
	# disable_keyboard_input()
	return in_value

def input_uint(title):
	while True:
		# enable_keyboard_input()
		in_value = input(title)
		# disable_keyboard_input()
		if in_value.isdigit():
			return int(in_value)



def print_buffer():
	global _buffer
	print(_buffer, end="")

def print_in_buffer(printable):
	global _buffer
	_buffer += printable + "\n"



def main():
	title = input_title("Title: ")
	work_time_minutes = input_uint("Work interval time in Minutes: ")
	break_time_minutes = input_uint("Break interval time in Minutes: ")
	work_time_seconds = work_time_minutes * 60
	break_time_seconds = break_time_minutes * 60
	intervals = input_uint("Intervals Count: ")
	duration = intervals * (work_time_minutes + break_time_minutes)
	clear_console()

	txt_report = ""
	json_report = dict()
	pdf_report = None

	print_in_buffer(F"MPomidoro")
	print_in_buffer(F"{title}")
	print_in_buffer(F"{intervals} x {work_time_minutes}min {break_time_minutes}min")
	print_in_buffer(F"")



	begin = datetime.now()

	for interval_i in range(0, intervals):
		for work_i in range(0, work_time_seconds):
			time.sleep(1)
			clear_console()
			print_buffer()
			ml = (work_time_seconds - work_i) // 60
			ml = F"0{ml}" if ml < 10 else ml
			ms = (work_time_seconds - work_i) % 60
			ms = F"0{ms}" if ms < 10 else ms
			print(f"{YELLOW}WORK #{interval_i+1} {ml}:{ms}{RESET}")
		clear_console()
		print_in_buffer(F"{GREEN}WORK #{interval_i+1} {work_time_minutes}min{RESET}")
		print_buffer()
		for break_i in range(0, break_time_seconds):
			time.sleep(1)
			clear_console()
			print_buffer()
			ml = (break_time_seconds - break_i) // 60
			ml = F"0{ml}" if ml < 10 else ml
			ms = (break_time_seconds - break_i) % 60
			ms = F"0{ms}" if ms < 10 else ms
			print(f"{YELLOW}BREAK #{interval_i+1} {ml}:{ms}{RESET}")
		clear_console()
		print_in_buffer(F"{GREEN}BREAK #{interval_i+1} {break_time_minutes}min{RESET}")
		print_buffer()
	clear_console()
	print_in_buffer(F"")
	print_buffer()

	end = datetime.now()



	begin_year = begin.strftime("%Y")
	begin_month = begin.strftime("%m")
	begin_day = begin.strftime("%d")
	begin_hour = begin.strftime("%H")
	begin_minute = begin.strftime("%M")

	end_year = end.strftime("%Y")
	end_month = end.strftime("%m")
	end_day = end.strftime("%d")
	end_hour = end.strftime("%H")
	end_minute = end.strftime("%M")

	conclusions = input_title("Conclusions: ")



	txt_report += F"MPomidoro Report\n"
	txt_report += F"Title: {title}\n"
	txt_report += F"Date: {begin.strftime("%Y.%m.%d")}\n"
	txt_report += F"Begin: {begin_hour}:{begin_minute}\n"
	txt_report += F"End: {end_hour}:{end_minute}\n"
	txt_report += F"Duration: {duration}min\n"
	txt_report += F"Conclusions: {conclusions}\n"
	txt_report += F"\n"
	for i in range(0, intervals):
		txt_report += F"✓ WORK #{i+1} {work_time_minutes}min\n"
		txt_report += F"✓ BREAK #{i+1} {break_time_minutes}min\n"

	filepath = F"./Reports/{begin_year}/{begin_month}/{begin_year}_{begin_month}_{begin_day}_{begin_hour}{begin_minute}_{title.replace(" ", "_")}.txt"

	os.makedirs(os.path.dirname(filepath), exist_ok=True)
	with open(filepath, "w", encoding="utf-8") as file:
		file.write(txt_report)



if __name__ == "__main__":
	main()
[–] mietkiewski_dev@programming.dev -2 points 4 hours ago (1 children)

Hey, could you remove the full Main.py from your comment? The project is closed‑source, so sharing the entire file isn’t allowed. Thanks!

[–] graynk@discuss.tchncs.de 4 points 1 hour ago

The project is closed‑source

It's not though. It may not be FOSS, and by omitting a license you do keep the copyright by default, but it's definitely not closed source either, it's "source available". Unless I'm missing the joke?

[–] mietkiewski_dev@programming.dev 3 points 10 hours ago (1 children)

Starting has always been the hardest part for me. Curious what helps you get going — I’m still figuring it out myself.

[–] ExperimentalGuy@programming.dev 2 points 7 hours ago (1 children)

Finding music that locks me in is key.

[–] mietkiewski_dev@programming.dev 1 points 4 hours ago

Nice... Music definitely helps.