thyme 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +13 -30
- data/thyme +6 -1
- data/thyme.rb +108 -1
- data/thyme_test.rb +22 -4
- metadata +18 -2
data/README.md
CHANGED
@@ -14,7 +14,7 @@ Usage
|
|
14
14
|
Start thyme with:
|
15
15
|
|
16
16
|
$ thyme
|
17
|
-
[
|
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 :
|
35
|
+
set :tmux, true
|
36
36
|
|
37
|
-
option :o, :open, '
|
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
|
-
|
42
|
+
`mplayer ~/music/flight-of-the-bumble-bee.mp3 &`
|
43
43
|
end
|
44
44
|
|
45
45
|
after do
|
46
|
-
`
|
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
|
-
* `:
|
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
|
-
|
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
|
64
|
+
For tmux integration, make sure to set the `:tmux` option in `~/.thymerc`:
|
67
65
|
|
68
|
-
set :
|
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
|
-
|
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.
|
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
|
3
|
+
require 'minitest'
|
4
4
|
|
5
|
-
|
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
|
10
|
-
|
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.
|
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-
|
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
|