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

  • three@piefed.social
    link
    fedilink
    English
    arrow-up
    7
    ·
    23 hours ago
    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()
    
      • graynk@discuss.tchncs.de
        link
        fedilink
        arrow-up
        4
        ·
        16 hours 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?

      • Otter@lemmy.ca
        link
        fedilink
        arrow-up
        1
        ·
        15 hours ago

        That comment is helping potential users vet your project before they use it, since not everyone has the motivation to go into the repo and take a look

        • mietkiewski_dev@programming.devOP
          link
          fedilink
          arrow-up
          2
          ·
          2 hours ago

          Just to clarify — I don’t have any issue with people analyzing or quoting small parts of the code. The project is intentionally distributed on Gumroad as a “0$+” closed‑source release rather than as an open‑source GitHub repo. Since there’s no license file, it defaults to all rights reserved, which means full files can’t be redistributed.

          Part of this project is also a learning exercise for me in how to package and distribute small tools. I’m genuinely interested in feedback on this approach.

          But if someone posts the entire file publicly, it makes it harder for me to actually demonstrate the distribution model I’m experimenting with — the whole point was to release it through Gumroad, not as a fully exposed source dump.

          • graynk@discuss.tchncs.de
            link
            fedilink
            arrow-up
            2
            ·
            2 hours ago

            Since there’s no license file, it defaults to all rights reserved, which means full files can’t be redistributed.

            I’m not a lawyer, but I would argue this actually means that even people who get it from Gumroad can’t use it “legally”. There should be a license which expresses your intent.

    • ZweiEuro@lemmy.world
      link
      fedilink
      arrow-up
      1
      ·
      edit-2
      2 hours ago

      I feel like this might sound unhealthy of me but: The angrier/more frustrated I get, the better. Angry isnt bad in my head, angry at $thing gets shit done because I do not want to see it or have it in my head anymore than necessary.

      Though I enjoy once I start even if I hate $thing since I like computers/coding/learning.

      This single thing got me through university. I dont want to do $thing -> not doing it keeps it on my mind -> once I have a single minute free I will make a plan where to begin the thing -> when I have a good chunk of the time I may need for it I do it just so the thing is finally gone.

      Healthy? Up for debate. Can’t argue with the results tho…

      Edit: I am typically a very jolly and happy Person ^^ there is just this research and writing stuff in uni where it feels like pleasing some arbitrary line the prof drew ._.