thyme 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (5) hide show
  1. data/README.md +13 -30
  2. data/thyme +6 -1
  3. data/thyme.rb +108 -1
  4. data/thyme_test.rb +22 -4
  5. metadata +18 -2
data/README.md CHANGED
@@ -14,7 +14,7 @@ Usage
14
14
  Start thyme with:
15
15
 
16
16
  $ thyme
17
- [=.........................] 25m
17
+ [=== ] 24:59
18
18
 
19
19
  You'll have 25 minutes by default. `Ctrl-C` to interrupt. You can also start
20
20
  it in daemon mode, which is only useful if you've got tmux integration to notify
@@ -32,66 +32,49 @@ Thyme is configurable and extensible. All configurations live in the
32
32
  `~/.thymerc` file:
33
33
 
34
34
  set :timer, 25
35
- set :outfile, "~/.thyme-tmux"
35
+ set :tmux, true
36
36
 
37
- option :o, :open, 'opens today & records sheets' do
38
- `vim -O ~/.thyme-today.md ~/.thyme-records.md`
37
+ option :o, :open, 'open sheets' do
38
+ `vim -O ~/.thyme-today.md ~/.thyme-records.md < \`tty\` > \`tty\``
39
39
  end
40
40
 
41
41
  before do
42
- puts "Get ready, get set, GO!"
42
+ `mplayer ~/music/flight-of-the-bumble-bee.mp3 &`
43
43
  end
44
44
 
45
45
  after do
46
- `mplayer ~/music/wohoo.mp3`
47
- `vim -O ~/.thyme-today.md`
46
+ `notify-send -u critical "0:00 Thymes Up!"`
48
47
  end
49
48
 
50
49
  The `set` method sets different configurations. There are only two:
51
50
 
52
51
  * `:timer` is the number of minutes to countdown from
53
- * `:outfile` is the file to write out progress to for tmux integration
52
+ * `:tmux` is whether or not you want tmux integration on (off by default)
54
53
 
55
54
  The `option` method adds new options to the `thyme` command. In the above
56
55
  example, we can now execute `thyme -o`. Use `thyme -h` to see available
57
56
  options.
58
57
 
59
58
  The `before` and `after` adds hooks to our timer. Now before the timer starts,
60
- STDOUT will receive a message. After the timer ends, vim will open our today
61
- sheet.
59
+ an mp3 will play. After the timer ends, a notification will be sent.
62
60
 
63
61
  Integration
64
62
  ===========
65
63
 
66
- For tmux integration, make sure to set the outfile in `~/.thymerc`:
64
+ For tmux integration, make sure to set the `:tmux` option in `~/.thymerc`:
67
65
 
68
- set :outfile, "~/.thyme-tmux"
66
+ set :tmux, true
69
67
 
70
68
  Then in your `.tmux.conf` file:
71
69
 
72
70
  set-option -g status-right '#(cat ~/.thyme-tmux)'
71
+ set-option -g status-interval 1
73
72
 
74
73
  For vim integration, I like to execute `thyme -d` to toggle the timer. This only
75
74
  works if you have tmux integration setup for the countdown:
76
75
 
77
- nmap <leader>t :!thyme -d
78
- nmap <leader>T :!thyme -s
79
-
80
- TODO
81
- ====
82
-
83
- * add directory stucture (binary, lib file, tests, Rakefile, gemspec)
84
- * add `--help`
85
- * add 25 minute timer
86
- * add progress bar
87
- * add `--daemon` switch and `--stop`
88
- * add config reader
89
- * add config `set`
90
- * add `set :timer`
91
- * add `set :outfile`
92
- * add config `option`
93
- * add config `before` and `after`
94
- * add color to outfile tmux integration (?)
76
+ nmap <leader>t :!thyme -d<cr>
77
+ nmap <leader>T :!thyme -s<cr>
95
78
 
96
79
  License
97
80
  =======
data/thyme CHANGED
@@ -2,11 +2,16 @@
2
2
  require 'optparse'
3
3
  require File.expand_path('thyme', File.dirname(__FILE__))
4
4
 
5
+ $0 = 'thyme'
5
6
  ARGV.options do |o|
7
+ thyme = Thyme.new
8
+ thyme.load_config(o)
6
9
  o.set_summary_indent(' ')
7
10
  o.banner = "Usage: #{File.basename($0)} [OPTION]"
8
11
  o.define_head "Timer for Pomodoro Technique"
12
+ o.on('-d', '--daemon', 'run in background') { thyme.daemonize! }
9
13
  o.on('-h', '--help', 'show this help message') { puts o; exit }
14
+ o.on('-s', '--stop', 'stops timer') { thyme.stop; exit }
10
15
  o.parse!
11
- puts o
16
+ thyme.run
12
17
  end
data/thyme.rb CHANGED
@@ -1,4 +1,111 @@
1
+ require 'ruby-progressbar'
2
+ require 'date'
3
+
1
4
  class Thyme
2
- VERSION = '0.0.1'
5
+ VERSION = '0.0.2'
3
6
  CONFIG_FILE = "#{ENV['HOME']}/.thymerc"
7
+ PID_FILE = "#{ENV['HOME']}/.thyme-pid"
8
+ TMUX_FILE = "#{ENV['HOME']}/.thyme-tmux"
9
+ OPTIONS = [:timer, :tmux]
10
+
11
+ def initialize
12
+ @timer = 25
13
+ @tmux = false
14
+ end
15
+
16
+ def run
17
+ @before.call if @before
18
+ start = @timer * 60
19
+ start_time = DateTime.now
20
+ seconds = start + 1
21
+ min_length = (seconds / 60).floor.to_s.length
22
+ tmux_file = File.open(TMUX_FILE, "w")
23
+ bar = ProgressBar.create(
24
+ title: format(seconds-1, min_length),
25
+ total: seconds,
26
+ length: 50,
27
+ format: '[%B] %t')
28
+ while !bar.finished? && seconds > 0
29
+ seconds = start - seconds_since(start_time)
30
+ title = format(seconds, min_length)
31
+ fg = color(seconds)
32
+ bar.title = title
33
+ bar.increment
34
+ if @tmux
35
+ tmux_file.truncate(0)
36
+ tmux_file.rewind
37
+ tmux_file.write("#[default]#[fg=#{fg}]#{title}#[default]")
38
+ tmux_file.flush
39
+ end
40
+ sleep(1)
41
+ end
42
+ rescue SignalException => e
43
+ puts ""
44
+ ensure
45
+ tmux_file.close
46
+ @after.call if @after && seconds <= 0
47
+ stop
48
+ end
49
+
50
+ def stop
51
+ File.delete(TMUX_FILE) if File.exists?(TMUX_FILE)
52
+ if File.exists?(PID_FILE)
53
+ pid = File.read(PID_FILE).to_i
54
+ File.delete(PID_FILE)
55
+ Process.kill('TERM', pid) if pid > 1
56
+ end
57
+ end
58
+
59
+ def daemonize!
60
+ Process.daemon
61
+ File.open(PID_FILE, "w") { |f| f.print(Process.pid) }
62
+ end
63
+
64
+ def set(opt, val)
65
+ raise ThymeError.new("Invalid option: #{opt}") if !OPTIONS.include?(opt.to_sym)
66
+ self.instance_variable_set("@#{opt}", val)
67
+ end
68
+
69
+ def before(&block)
70
+ @before = block
71
+ end
72
+
73
+ def after(&block)
74
+ @after = block
75
+ end
76
+
77
+ def option(optparse, short, long, desc, &block)
78
+ optparse.on("-#{short}", "--#{long}", desc) { block.call; exit }
79
+ end
80
+
81
+ def load_config(optparse)
82
+ return if !File.exists?(CONFIG_FILE)
83
+ app = self
84
+ Object.class_eval do
85
+ define_method(:set) { |opt,val| app.set(opt,val) }
86
+ define_method(:before) { |&block| app.before(&block) }
87
+ define_method(:after) { |&block| app.after(&block) }
88
+ define_method(:option) { |sh,lo,desc,&b| app.option(optparse,sh,lo,desc,&b) }
89
+ end
90
+ load(CONFIG_FILE, true)
91
+ end
92
+
93
+ private
94
+ def seconds_since(time)
95
+ ((DateTime.now - time) * 24 * 60 * 60).to_i
96
+ end
97
+
98
+ def format(seconds, min_length)
99
+ min = (seconds / 60).floor
100
+ lead = ' ' * (min_length - min.to_s.length)
101
+ sec = (seconds % 60).floor
102
+ sec = "0#{sec}" if sec.to_s.length == 1
103
+ "#{lead}#{min}:#{sec}"
104
+ end
105
+
106
+ def color(seconds)
107
+ seconds < (5*60) ? 'red,bold' : 'default'
108
+ end
4
109
  end
110
+
111
+ class ThymeError < StandardError; end;
data/thyme_test.rb CHANGED
@@ -1,12 +1,30 @@
1
1
  require 'rubygems'
2
2
  require "#{File.dirname(__FILE__)}/thyme"
3
- require 'minitest/autorun'
3
+ require 'minitest'
4
4
 
5
- class ThymeTest < MiniTest::Unit::TestCase
5
+ Minitest.autorun
6
+
7
+ class ThymeTest < Minitest::Test
6
8
  def setup
9
+ @thyme = Thyme.new
10
+ end
11
+
12
+ def test_format
13
+ assert_equal('25:00', @thyme.send(:format, 25*60, 2))
14
+ assert_equal('24:59', @thyme.send(:format, 25*60-1, 2))
15
+ assert_equal(' 5:00', @thyme.send(:format, 5*60, 2))
16
+ assert_equal(' 4:05', @thyme.send(:format, 4*60+5, 2))
17
+ end
18
+
19
+ def test_color
20
+ assert_equal('default', @thyme.send(:color, 5*60))
21
+ assert_equal('red,bold', @thyme.send(:color, 5*60-1))
7
22
  end
8
23
 
9
- def test_truth
10
- assert(true)
24
+ def test_set
25
+ assert_equal(25, @thyme.instance_variable_get('@timer'))
26
+ @thyme.set(:timer, 20)
27
+ assert_equal(20, @thyme.instance_variable_get('@timer'))
28
+ assert_raises(ThymeError) { @thyme.set(:invalid, nil) }
11
29
  end
12
30
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: thyme
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,8 +9,24 @@ authors:
9
9
  autorequire:
10
10
  bindir: .
11
11
  cert_chain: []
12
- date: 2013-05-30 00:00:00.000000000 Z
12
+ date: 2013-05-31 00:00:00.000000000 Z
13
13
  dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: ruby-progressbar
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
14
30
  - !ruby/object:Gem::Dependency
15
31
  name: minitest
16
32
  requirement: !ruby/object:Gem::Requirement