Skip to content

Instantly share code, notes, and snippets.

@biangle
Created August 27, 2010 15:19
Show Gist options
  • Select an option

  • Save biangle/553555 to your computer and use it in GitHub Desktop.

Select an option

Save biangle/553555 to your computer and use it in GitHub Desktop.
---
task: 25
break: 5
coffee: 30
#encoding: utf-8
#
# PomTk - GUI utility for Pomodoro technique via Ruby/Tk.
#
# Author: biangle <[email protected]>
# License: MIT License
#
require 'tk'
require 'logger'
require 'fileutils'
require 'yaml'
class PomTk
PROGNAME = 'PomTk'.freeze
VERSION = '0.0.1'.freeze
LOG_DIR = File.join(ENV['HOME'], '.pomtk').freeze
LOG_NAME = 'pom.log'.freeze
LOG_AGE = 'daily'.freeze
CONFIG_PATH = File.join(ENV['HOME'], '.pomtk.yaml').freeze
DEFAULT_CONFIG = { 'task' => 25, 'break' => 5, 'coffee' => 30 }.freeze
# Simple timer class.
class Timer
# Create a new Timer object with waiting seconds.
def initialize(sec)
@sec = sec
@start_time = nil
@thread = nil
end
# Launch a new thread and return immediatly.
# The thread executes the given block after the timer seconds.
def wait_and
@thread = Thread.new do
@start_time = Time.now
sleep @sec
yield
end
end
# Stop the timer thread explicitly.
def stop
@thread.stop
@thread = nil
end
# Rest seconds.
def rest
@sec - (Time.now - @start_time)
end
end # class Timer
# Ruby/Tk extensions
class ::TkButton
def disable
state 'disabled'
end
def enable
state 'normal'
end
end # class TkButton
#
# Class methods
#
def self.launch
new.launch
end
#
# Instance methods
#
attr_reader :start_button
def initialize
ensure_log_dir
@config = load_config
@log = create_logger
@log.info sprintf('%s start (task: %d, break: %d, coffee: %d [min]).',
program_name, @config['task'],
@config['break'], @config['coffee'])
@pom_count = 1
@timer = Timer.new(@config['task'] * 60)
@break_timer = Timer.new(@config['break'] * 60)
@coffee_timer = Timer.new(@config['coffee'] * 60)
@display = nil
@start_button = nil
create_window
end
def ensure_log_dir
FileUtils.mkdir_p LOG_DIR
end
def create_logger
logger = Logger.new(File.join(LOG_DIR, LOG_NAME), LOG_AGE)
logger.progname = program_name
logger.formatter = proc {|severity, datetime, progname, message|
"[#{datetime.strftime('%H:%M:%S')}] #{message}\n"
}
logger.level = Logger::INFO
logger
end
def program_name
"#{PROGNAME} v#{VERSION}"
end
def load_config
return DEFAULT_CONFIG unless File.file?(CONFIG_PATH)
DEFAULT_CONFIG.merge YAML.load_file(CONFIG_PATH)
end
def launch
Tk.mainloop
@log.info 'quit.'
@log.close
end
def create_window
Tk.root.title = program_name
@display = TkLabel.new(:text => '0 poms').pack(:fill => :x)
button_proc = proc {
start_button.disable
start_countdown
}
@start_button = TkButton.new(:text => 'START',
:command => button_proc).pack
end
def start_countdown
display sprintf('pomodoro %d.', @pom_count)
@start_button.text = 'RUNNING'
@timer.wait_and do
@log.info "DONE: " + guess_what_task
take_break
end
end
def display(msg)
@display.text = msg
@log.info msg
end
def guess_what_task
window = TkToplevel.new
window.title = %q{It's time to break!}
TkLabel.new(window) do
text %q{It's time to break! What task have you finished?}
pack
end
entry = TkEntry.new(window).pack(:fill => :x)
value = nil
thread = Thread.new{ Thread.stop; value = entry.value; window.destroy }
entry.bind('KeyPress-Return'){ thread.run }
window.protocol("WM_DELETE_WINDOW"){ thread.run }
window.attributes(:topmost, 1)
entry.focus
thread.join
Tk.root.attributes(:topmost, 1)
value
end
def take_break
if 0 == (@pom_count % 4)
display 'coffee break.'
@coffee_timer.wait_and{ finish_pom }
return
end
display 'break.'
@break_timer.wait_and{ finish_pom }
end
def finish_pom
@log.info sprintf('pomodoro %d finished.', @pom_count)
@display.text = sprintf('%d poms', @pom_count)
@start_button.text = 'START'
@pom_count += 1
@start_button.enable
end
end # class PomTk
#!/usr/bin/env rubyw
#encoding: utf-8
#
# PomTk - GUI utility for Pomodoro technique via Ruby/Tk.
#
# Author: biangle <[email protected]>
# License: MIT License
#
require 'rubygems'
require 'pomtk'
PomTk.launch
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment