thyme 0.0.10 → 0.0.16

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.
@@ -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: []