Ruby pomodoro timer with exceptional tunes

Greetings Ruby pals. I've been using the pomodoro system off and on for maybe a decade. It's not like, a big thing I'm into. It's just I've found it nifty to help rein in my focus when I want to give it a kick in the shorts.

TL;DR for the uninitiated: You set a 25 minute timer. Work without ANY distraction. At the end of the "pomodoro" you set a 5 minute timer. Get up. Eyes off screen. Stretch. Every four pomodoros you take a 15 minute break. I find it can help with focus and endurance. Your eyes don't get spun out as fast.

But here's what I'm thinking.

My actual kitchen timer STINKS. It's cute. But too inaccurate.

And the google timer looks cool. But, it's too easy to mute and when unmuted it is about as loud as my scream when stepping on a lego. And you can't modulate the volume. I've nearly dumped my Ovaltine all over my precious mechanical keyboard TOO MANY TIMES to keep using this timer.

SO. pomo. It is inspired by TJ Holowaychuk's pomo I'm pretty sure I used in 2014. It's a lightweight executable you can pop in your /usr/local/bin/pomo, sprinkle a little chmod +x /usr/local/bin/pomo magic on it, and BOOM! Pomotization complete.

#!/usr/bin/env ruby
require 'bloops'
require 'io/console'

TOTAL_TIME = 25 * 60  # 25 minutes in seconds
CHIRP_TIME = 5 * 60   # 5 minutes in seconds

def format_time(seconds)
  minutes = seconds / 60
  seconds = seconds % 60
  format("%02d:%02d", minutes, seconds)
end

def play_chirp
  b = Bloops.new
  b.tempo = 120
  sound = b.sound Bloops::SQUARE
  sound.volume = 0.3
  sound.sustain = 0.1
  b.tune sound, "C6 8"
  b.play
  sleep 0.5
end

def play_wild_song
  b = Bloops.new
  b.tempo = 360
  sound = b.sound Bloops::SAWTOOTH
  sound.volume = 0.5
  sound.sustain = 0.1
  sound.attack = 0.1
  sound.decay = 0.1
  b.tune sound, "C5 8 E5 8 G5 8 C6 8 G5 8 E5 8 C6 4 B5 4 A5 4 G5 4 F5 8 A5 8 C6 8 F6 8 C6 8 A5 8 F6 4 E6 4 D6 4 C6 4"
  b.play
  sleep 8 while !b.stopped?
end

start_time = Time.now
end_time = start_time + TOTAL_TIME
chirp_played = false

system('clear') || system('cls')

loop do
  remaining = (end_time - Time.now).to_i
  break if remaining <= 0

  print "\rPomodoro: #{format_time(remaining)} remaining"
  $stdout.flush

  if remaining <= CHIRP_TIME && !chirp_played
    play_chirp
    chirp_played = true
  end

  sleep 1
end

puts "\nPomodoro finished! Time for a break, valiant Rubyist!"
play_wild_song

Permalink

Once you run your pomo, you get a simple little 25 minute timer. It chirps at you with five minutes left. Then when it's done it plays you a badass tune.

bloopsaphone is an excellent project from why maybe 20 years ago to make rad tunes in Ruby. It still works. My team of freelance Ruby pros maintain it now.

So, the best bit is, you can be annoyingly ping'd to a tune of your choice! You can randomize it! Or jazz it up a bit! Let me know what you make.