thyme 0.0.10 → 0.0.16

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 5abf29ab5c23ad3c627e59ba2359fe9edadd4e29d3a9867a8bd5544bc3f4b9a1
4
+ data.tar.gz: 843d993b305a5e72067ba9e426f0b840fdc3f5f352c092fb3dff46087558c809
5
+ SHA512:
6
+ metadata.gz: 8258374971ba89526629690016690128b84cd3ba7a77adfaead03cdac0f463db4df4dbf02462938194f64483a9bd2f16fdd0a96c73a3f4a659745ffa401c4c52
7
+ data.tar.gz: 9bf433d64f8268e896a385e49777bb25d279f2b98af52bfc24c5598710dc1635a2161a54de9012aad992f762c9148b56dd45b816d699dc34e3322c7dad7d0796
data/README.md CHANGED
@@ -1,74 +1,76 @@
1
- Description
2
- ===========
1
+ # Description
3
2
 
4
3
  Thyme is a console pomodoro timer.
5
4
 
6
- Installation
7
- ============
5
+ # Installation
8
6
 
9
7
  $ gem install thyme
10
8
 
11
- Usage
12
- =====
9
+ # Usage
13
10
 
14
11
  Start thyme with:
15
12
 
16
13
  $ thyme
17
14
  [= ] 24:59
18
15
 
19
- You'll have 25 minutes by default. `Ctrl-C` to interrupt. You can also start
16
+ You'll have 25 minutes by default. `Ctrl-C` to interrupt. You can also start
20
17
  it in daemon mode, which is only useful if you've got tmux integration to notify
21
18
  you of the timer:
22
19
 
23
20
  $ thyme -d
24
21
 
25
- To interrupt the timer in daemon mode, simply run `thyme --stop`. Or wait 25
26
- minutes for it to kill itself.
22
+ Some other useful commands:
27
23
 
28
- Configure
29
- =========
24
+ $ thyme # run again to pause/unpause
25
+ $ thyme -s # stops daemon
26
+ $ thyme -d -r # repeats timer until you manually stop it
27
+ $ thyme -d -r 10 # repeats timer exactly 10 times
30
28
 
31
- Thyme is configurable and extensible. All configurations live in the
32
- `~/.thymerc` file:
29
+ # Configure
33
30
 
34
- set :timer, 25*60
35
- set :interval, 1
36
- set :tmux, true
37
- set :tmux_theme, "#[fg=mycolor,bg=mycolor]#[fg=%s]%s#[fg=mycolor,bg=mycolor]"
31
+ Configurations live in the `~/.thymerc` file:
38
32
 
39
- option :b, :break, 'start a break' do
40
- set :timer, 5*60
41
- run
42
- end
33
+ set :timer, 25*60 # 25 minute pomodoros
34
+ set :timer_break, 5*60 # 5 minute breaks
35
+ set :warning, 5*60 # show warning color in tmux at <5 minutes, 0 to disable
36
+ set :warning_color, 'red,bold' # warning color for tmux is red/bold
37
+ set :break_color, 'blue' # break color is blue
38
+ set :interval, 1 # refresh timer every 1 second
39
+ set :tmux, true # turn on tmux integration
40
+ set :tmux_theme, "#[fg=mycolor,bg=mycolor]#[fg=%s]%s#[fg=mycolor,bg=mycolor]"
43
41
 
42
+ # adds `-t --today` option, which opens a text file in vim
44
43
  option :t, :today, 'open today sheet' do
45
44
  `vim -O ~/.thyme-today.md ~/.thyme-records.md < \`tty\` > \`tty\``
46
45
  end
47
46
 
48
- before do
49
- `mplayer ~/music/flight-of-the-bumble-bee.mp3 &`
47
+ # adds `-s --seconds num` option, which allows on the fly timer
48
+ option :s, 'seconds num', 'run with custom seconds' do |num|
49
+ set :timer, num.to_i
50
+ @run = true
50
51
  end
51
52
 
52
- after do |seconds_left|
53
- `notify-send -u critical "Thymes Up!"` if seconds_left == 0
53
+ # execute hook before thyme program starts
54
+ before(:all) do
55
+ `mplayer ~/music/flight-of-the-bumble-bee.mp3 &`
54
56
  end
55
57
 
56
- The `set` method sets different configurations. There are only two:
57
-
58
- * `:timer` is the number of seconds to countdown from
59
- * `:interval` is the refresh rate of the progress bar and tmux status in seconds
60
- * `:tmux` is whether or not you want tmux integration on (off by default)
61
- * `:tmux_theme` optionally lets you format the tmux status
58
+ # execute hook before each pomodoro
59
+ before do
60
+ `terminal-notifier -message "Let's get started!"`
61
+ end
62
62
 
63
- The `option` method adds new options to the `thyme` command. In the above
64
- example, we can now execute `thyme -b` or `thyme -t`. Use `thyme -h` to see
65
- available options.
63
+ # execute hook after each pomodoro
64
+ after do |seconds_left|
65
+ `terminal-notifier -message "Thyme's Up!"` if seconds_left == 0
66
+ end
66
67
 
67
- The `before` and `after` adds hooks to our timer. Now before the timer starts,
68
- an mp3 will play. After the timer ends, a notification will be sent.
68
+ # execute hook after thyme program quits
69
+ after(:all) do
70
+ `mplayer ~/music/victory.mp3 &`
71
+ end
69
72
 
70
- Integration
71
- ===========
73
+ # Tmux
72
74
 
73
75
  For tmux integration, make sure to set the `:tmux` option in `~/.thymerc`:
74
76
 
@@ -79,14 +81,55 @@ Then in your `.tmux.conf` file:
79
81
  set-option -g status-right '#(cat ~/.thyme-tmux)'
80
82
  set-option -g status-interval 1
81
83
 
82
- For vim integration, I like to execute `thyme -d` to toggle the timer. This only
84
+ For vim integration, I like to execute `thyme -d` to toggle the timer. This only
83
85
  works if you have tmux integration setup for the countdown:
84
86
 
85
87
  nmap <leader>t :!thyme -d<cr>
86
- nmap <leader>T :!thyme -s<cr>
87
88
 
88
- License
89
- =======
89
+ # Plugins
90
+
91
+ Thyme's functionality can also be extended with plugins. They'll usually be installed
92
+ in `~/.thymerc` like this:
93
+
94
+ require 'thyme_growl'
95
+ use ThymeGrowl, text: 'Go take a break!'
96
+
97
+ You can create your own plugins. They implement these methods:
98
+
99
+ class MyThymePlugin
100
+ def initialize(thyme, options={})
101
+ # `thyme` is an instance of Thyme::Config (see lib/thyme/config.rb)
102
+
103
+ # adds `-t --today` option, which opens a text file in vim
104
+ thyme.option :t, :today, 'open today sheet' do
105
+ `vim -O ~/.thyme-today.md ~/.thyme-records.md < \`tty\` > \`tty\``
106
+ end
107
+ end
108
+
109
+ def before_all
110
+ # code to run when thyme starts up
111
+ end
112
+
113
+ def before
114
+ # code to run when timer starts
115
+ end
116
+
117
+ def tick(seconds_left)
118
+ # code to run each tick
119
+ end
120
+
121
+ def after(seconds_left)
122
+ # code to run when timer stops
123
+ end
124
+
125
+ def after_all
126
+ # code to run when thyme program ends
127
+ end
128
+ end
129
+
130
+ The `before_all`, `before`, `tick`, `after`, and `after_all` methods are all optional.
131
+
132
+ # License
90
133
 
91
134
  Copyright Hugh Bien - http://hughbien.com.
92
135
  Released under BSD License, see LICENSE.md for more info.
data/bin/thyme CHANGED
@@ -1,17 +1,19 @@
1
1
  #!/usr/bin/env ruby
2
2
  require 'optparse'
3
- require File.expand_path('thyme', File.join(File.dirname(__FILE__), '..', 'lib'))
3
+ require_relative '../lib/thyme'
4
4
 
5
5
  $0 = 'thyme'
6
6
  ARGV.options do |o|
7
- thyme = Thyme.new
8
- thyme.load_config(o)
7
+ thyme = Thyme::Console.new
9
8
  o.set_summary_indent(' ')
10
- o.banner = "Usage: #{File.basename($0)} [OPTION]"
9
+ o.banner = "Usage: #{File.basename($0)} [OPTION]"
11
10
  o.define_head "Timer for Pomodoro Technique"
11
+ o.on('-b', '--break', 'run break timer') { thyme.break! }
12
12
  o.on('-d', '--daemon', 'run in background') { thyme.daemonize! }
13
13
  o.on('-h', '--help', 'show this help message') { puts o; exit }
14
- o.on('-s', '--stop', 'stops timer') { thyme.stop; exit }
14
+ o.on('-r', '--repeat [COUNT]', 'repeat timer') { |count| thyme.repeat!(count) }
15
+ o.on('-s', '--stop', 'stops running timer') { thyme.stop; exit }
16
+ thyme.load(o)
15
17
  o.parse!
16
18
  thyme.run
17
19
  end
@@ -1,120 +1,10 @@
1
- require 'ruby-progressbar'
2
1
  require 'date'
3
-
4
- class Thyme
5
- VERSION = '0.0.10'
6
- CONFIG_FILE = "#{ENV['HOME']}/.thymerc"
7
- PID_FILE = "#{ENV['HOME']}/.thyme-pid"
8
- TMUX_FILE = "#{ENV['HOME']}/.thyme-tmux"
9
- OPTIONS = [:timer, :tmux, :interval, :tmux_theme]
10
-
11
- def initialize
12
- @timer = 25 * 60
13
- @tmux = false
14
- @interval = 1
15
- @tmux_theme = "#[default]#[fg=%s]%s#[default]"
16
- end
17
-
18
- def run
19
- before_hook = @before
20
- seconds_start = @timer
21
- seconds_left = seconds_start + 1
22
- start_time = DateTime.now
23
- min_length = (seconds_left / 60).floor.to_s.length
24
- tmux_file = File.open(TMUX_FILE, "w")
25
- bar = ProgressBar.create(
26
- title: format(seconds_left-1, min_length),
27
- total: seconds_start,
28
- length: 50,
29
- format: '[%B] %t')
30
- while seconds_left > 0
31
- seconds_passed = seconds_since(start_time)
32
- seconds_left = [seconds_start - seconds_passed, 0].max
33
- title = format(seconds_left, min_length)
34
- fg = color(seconds_left)
35
- bar.title = title
36
- bar.progress = seconds_passed
37
- if @tmux
38
- tmux_file.truncate(0)
39
- tmux_file.rewind
40
- tmux_file.write(@tmux_theme % [fg, title])
41
- tmux_file.flush
42
- end
43
- if before_hook
44
- self.instance_exec(&before_hook)
45
- before_hook = nil
46
- end
47
- sleep(@interval)
48
- end
49
- rescue SignalException => e
50
- puts ""
51
- ensure
52
- tmux_file.close
53
- File.delete(TMUX_FILE) if File.exists?(TMUX_FILE)
54
- File.delete(PID_FILE) if File.exists?(PID_FILE)
55
- seconds_left = [seconds_start - seconds_since(start_time), 0].max
56
- self.instance_exec(seconds_left, &@after) if @after
57
- end
58
-
59
- def stop
60
- return if !File.exists?(PID_FILE)
61
- pid = File.read(PID_FILE).to_i
62
- File.delete(PID_FILE)
63
- Process.kill('TERM', pid) if pid > 1
64
- end
65
-
66
- def daemonize!
67
- Process.daemon
68
- File.open(PID_FILE, "w") { |f| f.print(Process.pid) }
69
- end
70
-
71
- def set(opt, val)
72
- raise ThymeError.new("Invalid option: #{opt}") if !OPTIONS.include?(opt.to_sym)
73
- self.instance_variable_set("@#{opt}", val)
74
- end
75
-
76
- def before(&block)
77
- @before = block
78
- end
79
-
80
- def after(&block)
81
- @after = block
82
- end
83
-
84
- def option(optparse, short, long, desc, &block)
85
- optparse.on("-#{short}", "--#{long}", desc) { self.instance_exec(&block); exit }
86
- end
87
-
88
- def load_config(optparse)
89
- return if !File.exists?(CONFIG_FILE)
90
- app = self
91
- Object.class_eval do
92
- define_method(:set) { |opt,val| app.set(opt,val) }
93
- define_method(:before) { |&block| app.before(&block) }
94
- define_method(:after) { |&block| app.after(&block) }
95
- define_method(:option) { |sh,lo,desc,&b| app.option(optparse,sh,lo,desc,&b) }
96
- end
97
- load(CONFIG_FILE, true)
98
- end
99
-
100
- private
101
- def seconds_since(time)
102
- ((DateTime.now - time) * 24 * 60 * 60).to_i
103
- end
104
-
105
- def format(seconds, min_length)
106
- min = (seconds / 60).floor
107
- lead = ' ' * (min_length - min.to_s.length)
108
- sec = (seconds % 60).floor
109
- sec = "0#{sec}" if sec.to_s.length == 1
110
- @interval < 60 ?
111
- "#{lead}#{min}:#{sec}" :
112
- "#{lead}#{min}m"
113
- end
114
-
115
- def color(seconds)
116
- seconds < (5*60) ? 'red,bold' : 'default'
117
- end
118
- end
119
-
120
- class ThymeError < StandardError; end;
2
+ require 'ruby-progressbar'
3
+ require_relative 'thyme/config'
4
+ require_relative 'thyme/console'
5
+ require_relative 'thyme/error'
6
+ require_relative 'thyme/format'
7
+ require_relative 'thyme/hooks_plugin'
8
+ require_relative 'thyme/timer'
9
+ require_relative 'thyme/tmux'
10
+ require_relative 'thyme/version'
@@ -0,0 +1,78 @@
1
+ module Thyme
2
+ # Configure state for the application. This can be done via the thymerc file or CLI flags.
3
+ # Public methods in this file are exposed to the thymerc file.
4
+ class Config
5
+ CONFIG_FILE = "#{ENV['HOME']}/.thymerc"
6
+ PID_FILE = "#{ENV['HOME']}/.thyme-pid"
7
+ TMUX_FILE = "#{ENV['HOME']}/.thyme-tmux"
8
+ OPTIONS = [:default_color, :break_color, :interval, :timer, :timer_break, :tmux, :tmux_theme, :warning, :warning_color]
9
+ OPTIONS.each { |opt| attr_reader(opt) }
10
+ attr_accessor :break, :daemon, :repeat, :repeat_index, :optparse
11
+
12
+ def initialize
13
+ # options set via config file
14
+ @break_color = 'default'
15
+ @default_color = 'default'
16
+ @interval = 1
17
+ @timer = 25 * 60
18
+ @timer_break = 5 * 60
19
+ @tmux = false
20
+ @tmux_theme = "#[default]#[fg=%s]%s#[default]"
21
+ @warning = 5 * 60
22
+ @warning_color = 'red,bold'
23
+
24
+ # plugins set via config file
25
+ @plugins = []
26
+ @hooks_plugin = use(Thyme::HooksPlugin)
27
+
28
+ # settings via command line
29
+ @break = false
30
+ @daemon = false
31
+ @repeat = 1
32
+ @repeat_index = 1
33
+ end
34
+
35
+ def set(opt, val)
36
+ raise Thyme::Error.new("Invalid option: #{opt}") if !OPTIONS.include?(opt.to_sym)
37
+ self.instance_variable_set("@#{opt}", val)
38
+ end
39
+
40
+ def use(plugin_class, *args, &block)
41
+ plugin = plugin_class.new(self, *args, &block)
42
+ @plugins << plugin
43
+ plugin
44
+ end
45
+
46
+ def before(kind = :each, &block)
47
+ type = kind == :all ? :before_all : :before
48
+ @hooks_plugin.add(type, &block)
49
+ end
50
+
51
+ def after(kind = :each, &block)
52
+ type = kind == :all ? :after_all : :after
53
+ @hooks_plugin.add(type, &block)
54
+ end
55
+
56
+ def tick(&block)
57
+ @hooks_plugin.add(:tick, &block)
58
+ end
59
+
60
+ def option(short, long, desc, &block)
61
+ return if !@optparse
62
+ @optparse.on("-#{short}", "--#{long}", desc) do |*args|
63
+ self.instance_exec(*args, &block)
64
+ exit if !@run
65
+ end
66
+ end
67
+
68
+ def send_to_plugin(message, *args)
69
+ @plugins.each do |plugin|
70
+ begin
71
+ plugin.public_send(message, *args) if plugin.respond_to?(message)
72
+ rescue
73
+ $stderr.puts "Exception raised from #{plugin.class}:", $!, $@
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,58 @@
1
+ module Thyme
2
+ # Exposes application to the CLI in bin/thyme
3
+ class Console
4
+ attr_accessor :config
5
+
6
+ def initialize
7
+ @config = Config.new
8
+ end
9
+
10
+ def break!
11
+ @config.break = true
12
+ end
13
+
14
+ def daemonize!
15
+ @config.daemon = true
16
+ Process.daemon if !ENV['THYME_TEST']
17
+ end
18
+
19
+ def repeat!(count = 0)
20
+ @config.repeat = count.to_i
21
+ end
22
+
23
+ def stop
24
+ timer.stop
25
+ end
26
+
27
+ def run
28
+ timer.run
29
+ end
30
+
31
+ # Loads the thymerc configuration file. Requires optparse b/c users can extend CLI via thymerc
32
+ def load(optparse, &block)
33
+ return if block.nil? && !File.exists?(Config::CONFIG_FILE)
34
+ config = @config
35
+ config.optparse = optparse
36
+ environment = Class.new do
37
+ define_method(:set) { |opt,val| config.set(opt,val) }
38
+ define_method(:use) { |plugin,*args,&b| config.use(plugin,*args,&b) }
39
+ define_method(:before) { |*args,&block| config.before(*args,&block) }
40
+ define_method(:after) { |*args,&block| config.after(*args,&block) }
41
+ define_method(:tick) { |&block| config.tick(&block) }
42
+ define_method(:option) { |sh,lo,desc,&b| config.option(sh,lo,desc,&b) }
43
+ end.new
44
+
45
+ if block # for test environment
46
+ environment.instance_eval(&block)
47
+ else
48
+ environment.instance_eval(File.read(Config::CONFIG_FILE), Config::CONFIG_FILE)
49
+ end
50
+ end
51
+
52
+ private
53
+
54
+ def timer
55
+ Timer.new(@config)
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,4 @@
1
+ module Thyme
2
+ class Error < StandardError; end # catch all error for Thyme
3
+ class StopTimer < StandardError; end # used to stop repeat timers
4
+ end
@@ -0,0 +1,43 @@
1
+ module Thyme
2
+ # Methods used to nicely format output to the user
3
+ class Format
4
+ def initialize(config)
5
+ @config = config
6
+ end
7
+
8
+ def seconds_since(time)
9
+ ((DateTime.now - time) * 24 * 60 * 60).to_i
10
+ end
11
+
12
+ # Displays time depending on configured interval eg. 15m OR 15:20
13
+ def time_left(seconds, min_length)
14
+ min = (seconds / 60).floor
15
+ lead = ' ' * [0, min_length - min.to_s.length].max
16
+ sec = (seconds % 60).floor
17
+ sec = "0#{sec}" if sec.to_s.length == 1
18
+ @config.interval < 60 ?
19
+ "#{lead}#{min}:#{sec} #{repeat_subtitle}".sub(/\s*$/, '') :
20
+ "#{lead}#{min}m #{repeat_subtitle}".sub(/\s*$/, '')
21
+ end
22
+
23
+ def repeat_subtitle
24
+ if @config.repeat == 1
25
+ ''
26
+ elsif @config.repeat == 0
27
+ "(#{@config.repeat_index})"
28
+ else
29
+ "(#{@config.repeat_index}/#{@config.repeat})"
30
+ end
31
+ end
32
+
33
+ def tmux_color(seconds)
34
+ if @config.break
35
+ @config.break_color
36
+ elsif seconds < @config.warning
37
+ @config.warning_color
38
+ else
39
+ @config.default_color
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,33 @@
1
+ module Thyme
2
+ # Generic plugin for users to run Ruby code in Thyme event callbacks in thymerc
3
+ class HooksPlugin
4
+ def initialize(config)
5
+ @config = config
6
+ @hooks = {before_all: [], before: [], tick: [], after: [], after_all: []}
7
+ end
8
+
9
+ def add(type, &block)
10
+ @hooks[type] << block
11
+ end
12
+
13
+ def before_all
14
+ @hooks[:before_all].each { |b| @config.instance_exec(&b) }
15
+ end
16
+
17
+ def before
18
+ @hooks[:before].each { |b| @config.instance_exec(&b) }
19
+ end
20
+
21
+ def tick(seconds_left)
22
+ @hooks[:tick].each { |t| @config.instance_exec(seconds_left, &t) }
23
+ end
24
+
25
+ def after(seconds_left)
26
+ @hooks[:after].each { |a| @config.instance_exec(seconds_left, &a) }
27
+ end
28
+
29
+ def after_all
30
+ @hooks[:after_all].each { |a| @config.instance_exec(&a) }
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,124 @@
1
+ module Thyme
2
+ # The actual timer logic where you can pause, unpause, or stop one or more timers
3
+ class Timer
4
+ def initialize(config)
5
+ @config = config
6
+ @format = Format.new(config)
7
+ @tmux = Tmux.new(config)
8
+ end
9
+
10
+ def stop
11
+ send_signal('TERM')
12
+ end
13
+
14
+ def run
15
+ # pause/unpause timer if it's already running
16
+ send_signal('USR1') and return if File.exists?(Config::PID_FILE)
17
+
18
+ begin
19
+ File.open(Config::PID_FILE, "w") { |f| f.print(Process.pid) }
20
+ @tmux.open
21
+ if @config.repeat == 1
22
+ run_single
23
+ else
24
+ while @config.repeat_index <= @config.repeat || @config.repeat == 0
25
+ @config.break = false
26
+ run_single
27
+ if @config.repeat_index < @config.repeat || @config.repeat == 0
28
+ @config.break = true
29
+ run_single
30
+ end
31
+ @config.repeat_index += 1
32
+ end
33
+ end
34
+ rescue Thyme::StopTimer
35
+ # stop signal received
36
+ ensure
37
+ @tmux.close
38
+ File.delete(Config::PID_FILE) if File.exists?(Config::PID_FILE)
39
+ end
40
+ end
41
+
42
+ private
43
+
44
+ # TODO: refactor this method, too large!
45
+ def run_single
46
+ seconds_total = @config.break ? @config.timer_break : @config.timer
47
+ seconds_left = seconds_total + 1
48
+ start_time = DateTime.now
49
+ paused_time = nil
50
+ min_length = (seconds_left / 60).floor.to_s.length
51
+ started = false
52
+ @bar ||= ENV['THYME_TEST'].nil? && !@config.daemon ?
53
+ ProgressBar.create(
54
+ title: @format.time_left(seconds_left-1, min_length),
55
+ total: seconds_total,
56
+ length: 50,
57
+ format: '[%B] %t') : nil
58
+ @bar.reset if @bar
59
+ while seconds_left > 0
60
+ begin
61
+ if paused_time
62
+ sleep(@config.interval)
63
+ next
64
+ end
65
+ seconds_passed = @format.seconds_since(start_time)
66
+ seconds_left = [seconds_total - seconds_passed, 0].max
67
+ title = @format.time_left(seconds_left, min_length)
68
+ if @bar
69
+ @bar.title = title
70
+ if seconds_left == 0 && !last?
71
+ @bar.progress = seconds_passed - 0.01 # prevent bar from finishing
72
+ else
73
+ @bar.progress = seconds_passed
74
+ end
75
+ end
76
+ @tmux.tick(@format.tmux_color(seconds_left), title)
77
+ unless started
78
+ started = true
79
+ @config.send_to_plugin(:before_all) if first?
80
+ @config.send_to_plugin(:before)
81
+ end
82
+ @config.send_to_plugin(:tick, seconds_left)
83
+ sleep(@config.interval)
84
+ rescue SignalException => e
85
+ if e.signm == 'SIGUSR1' && paused_time.nil?
86
+ paused_time = DateTime.now
87
+ elsif e.signm == 'SIGUSR1'
88
+ delta = DateTime.now - paused_time
89
+ start_time += delta
90
+ paused_time = nil
91
+ else
92
+ puts ""
93
+ @interrupted = true
94
+ raise Thyme::StopTimer
95
+ end
96
+ end
97
+ end
98
+ ensure
99
+ seconds_left = [seconds_total - @format.seconds_since(start_time), 0].max
100
+ @config.send_to_plugin(:after, seconds_left)
101
+ @config.send_to_plugin(:after_all) if @interrupted || last?
102
+ end
103
+
104
+ def first?
105
+ @config.repeat == 1 || (!@config.break && @config.repeat_index == 1)
106
+ end
107
+
108
+ def last?
109
+ @config.repeat == @config.repeat_index
110
+ end
111
+
112
+ # Since timers can be daemonized, we'll use Unix signals to trigger events such as
113
+ # pause/unpause in a separate process.
114
+ def send_signal(signal)
115
+ pid = File.read(Config::PID_FILE).to_i
116
+ Process.kill(signal, pid) if pid > 1
117
+ rescue Errno::ESRCH, Errno::ENOENT # process is already dead, cleanup files
118
+ File.delete(Config::TMUX_FILE) if File.exists?(Config::TMUX_FILE)
119
+ File.delete(Config::PID_FILE) if File.exists?(Config::PID_FILE)
120
+ ensure
121
+ true
122
+ end
123
+ end
124
+ end
@@ -0,0 +1,31 @@
1
+ module Thyme
2
+ # Provides tmux integration. Thyme outputs the timer to TMUX_FILE. Tmux reads this file and
3
+ # outputs to its bar.
4
+ class Tmux
5
+ def initialize(config)
6
+ @config = config
7
+ end
8
+
9
+ def open
10
+ return if !@config.tmux
11
+ @tmux_file = File.open(Config::TMUX_FILE, "w")
12
+ @tmux_file.truncate(0)
13
+ @tmux_file.rewind
14
+ @tmux_file.write('')
15
+ @tmux_file.flush
16
+ end
17
+
18
+ def tick(color, title)
19
+ return if !@tmux_file
20
+ @tmux_file.truncate(0)
21
+ @tmux_file.rewind
22
+ @tmux_file.write(@config.tmux_theme % [color, title])
23
+ @tmux_file.flush
24
+ end
25
+
26
+ def close
27
+ @tmux_file.close if @tmux_file
28
+ File.delete(Config::TMUX_FILE) if File.exists?(Config::TMUX_FILE)
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,3 @@
1
+ module Thyme
2
+ VERSION = '0.0.16'
3
+ end
metadata CHANGED
@@ -1,32 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: thyme
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.10
5
- prerelease:
4
+ version: 0.0.16
6
5
  platform: ruby
7
6
  authors:
8
7
  - Hugh Bien
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2014-01-07 00:00:00.000000000 Z
11
+ date: 2020-10-19 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: ruby-progressbar
16
15
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
16
  requirements:
19
- - - ! '>='
17
+ - - "~>"
20
18
  - !ruby/object:Gem::Version
21
- version: '0'
19
+ version: '1.0'
22
20
  type: :runtime
23
21
  prerelease: false
24
22
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
23
  requirements:
27
- - - ! '>='
24
+ - - "~>"
28
25
  - !ruby/object:Gem::Version
29
- version: '0'
26
+ version: '1.0'
30
27
  description: Extensible and configurable timer for Pomodoro Technique.
31
28
  email:
32
29
  - hugh@hughbien.com
@@ -39,28 +36,35 @@ files:
39
36
  - README.md
40
37
  - bin/thyme
41
38
  - lib/thyme.rb
42
- homepage: http://thymerb.com
43
- licenses: []
39
+ - lib/thyme/config.rb
40
+ - lib/thyme/console.rb
41
+ - lib/thyme/error.rb
42
+ - lib/thyme/format.rb
43
+ - lib/thyme/hooks_plugin.rb
44
+ - lib/thyme/timer.rb
45
+ - lib/thyme/tmux.rb
46
+ - lib/thyme/version.rb
47
+ homepage: http://hughbien.com/thyme/
48
+ licenses:
49
+ - BSD
50
+ metadata: {}
44
51
  post_install_message:
45
52
  rdoc_options: []
46
53
  require_paths:
47
54
  - lib
48
55
  required_ruby_version: !ruby/object:Gem::Requirement
49
- none: false
50
56
  requirements:
51
- - - ! '>='
57
+ - - ">="
52
58
  - !ruby/object:Gem::Version
53
59
  version: '0'
54
60
  required_rubygems_version: !ruby/object:Gem::Requirement
55
- none: false
56
61
  requirements:
57
- - - ! '>='
62
+ - - ">="
58
63
  - !ruby/object:Gem::Version
59
64
  version: 1.3.6
60
65
  requirements: []
61
- rubyforge_project:
62
- rubygems_version: 1.8.23
66
+ rubygems_version: 3.1.2
63
67
  signing_key:
64
- specification_version: 3
68
+ specification_version: 4
65
69
  summary: Timer for Pomodoro Technique
66
70
  test_files: []