pomo 1.0.1 → 2.0.0
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/.gitignore +17 -0
- data/DEVELOPMENT +15 -0
- data/Gemfile +4 -0
- data/{History.md → HISTORY.md} +11 -1
- data/LICENSE.txt +22 -0
- data/README.md +186 -0
- data/Rakefile +6 -15
- data/bin/pomo +43 -26
- data/lib/pomo.rb +11 -25
- data/lib/pomo/break.rb +17 -0
- data/lib/pomo/configuration.rb +74 -0
- data/lib/pomo/github_task.rb +19 -19
- data/lib/pomo/list.rb +30 -18
- data/lib/pomo/notifier.rb +26 -0
- data/lib/pomo/notifier/growl.rb +17 -0
- data/lib/pomo/notifier/libnotify.rb +14 -0
- data/lib/pomo/notifier/notification_center.rb +13 -0
- data/lib/pomo/notifier/quicksilver.rb +12 -0
- data/lib/pomo/task.rb +127 -32
- data/lib/pomo/version.rb +2 -2
- data/pomo.gemspec +24 -32
- metadata +123 -82
- data/Manifest +0 -17
- data/Readme.md +0 -137
- data/spec/spec.opts +0 -2
- data/tasks/docs.rake +0 -13
- data/tasks/gemspec.rake +0 -3
- data/tasks/spec.rake +0 -25
data/lib/pomo/break.rb
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
if RUBY_PLATFORM =~ /darwin/
|
2
|
+
MACOS_FULL_VERSION = `/usr/bin/sw_vers -productVersion`.chomp
|
3
|
+
MACOS_VERSION = /(10\.\d+)(\.\d+)?/.match(MACOS_FULL_VERSION).captures.first.to_f
|
4
|
+
OS_VERSION = "Mac OS X #{MACOS_FULL_VERSION}"
|
5
|
+
MACOS = true
|
6
|
+
else
|
7
|
+
MACOS_FULL_VERSION = MACOS_VERSION = 0
|
8
|
+
OS_VERSION = RUBY_PLATFORM
|
9
|
+
MACOS = false
|
10
|
+
end
|
11
|
+
|
12
|
+
module Pomo
|
13
|
+
class Configuration
|
14
|
+
##
|
15
|
+
# Notification library.
|
16
|
+
#
|
17
|
+
# values: notification_center | libnotify | growl | quicksilver
|
18
|
+
|
19
|
+
attr_reader :notifier
|
20
|
+
|
21
|
+
##
|
22
|
+
# Write ~/.pomo_stat file.
|
23
|
+
#
|
24
|
+
# values: true | false
|
25
|
+
|
26
|
+
attr_accessor :pomo_stat
|
27
|
+
|
28
|
+
##
|
29
|
+
# Refresh tmux status bar.
|
30
|
+
#
|
31
|
+
# values: true | false
|
32
|
+
|
33
|
+
attr_accessor :tmux
|
34
|
+
|
35
|
+
##
|
36
|
+
# Initialize configuration.
|
37
|
+
def initialize
|
38
|
+
options = {
|
39
|
+
:notifier => default_notifier,
|
40
|
+
:pomo_stat => false,
|
41
|
+
:tmux => false
|
42
|
+
}
|
43
|
+
|
44
|
+
config_file = File.join(ENV['HOME'],'.pomorc')
|
45
|
+
|
46
|
+
if File.exists? config_file
|
47
|
+
config_options = YAML.load_file(config_file)
|
48
|
+
options.merge!(config_options)
|
49
|
+
else
|
50
|
+
File.open(config_file, 'w') { |file| YAML::dump(options, file) }
|
51
|
+
STDERR.puts "Initialized configuration file in #{config_file}"
|
52
|
+
end
|
53
|
+
|
54
|
+
@notifier = options[:notifier]
|
55
|
+
@pomo_stat = options[:pomo_stat]
|
56
|
+
@tmux = options[:tmux]
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
|
61
|
+
def default_notifier
|
62
|
+
if MACOS
|
63
|
+
if (10.8 <= MACOS_VERSION)
|
64
|
+
return 'notification_center'
|
65
|
+
else
|
66
|
+
return 'growl'
|
67
|
+
end
|
68
|
+
else
|
69
|
+
return 'libnotify'
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
end
|
data/lib/pomo/github_task.rb
CHANGED
@@ -3,52 +3,52 @@ module Pomo
|
|
3
3
|
class Task
|
4
4
|
def github?
|
5
5
|
false
|
6
|
-
end
|
6
|
+
end
|
7
7
|
end
|
8
|
-
|
8
|
+
|
9
9
|
class GithubTask < Task
|
10
|
-
|
10
|
+
|
11
11
|
##
|
12
12
|
# Username.
|
13
|
-
|
13
|
+
|
14
14
|
attr_accessor :username
|
15
|
-
|
15
|
+
|
16
16
|
##
|
17
17
|
# Project name.
|
18
|
-
|
18
|
+
|
19
19
|
attr_accessor :project
|
20
|
-
|
20
|
+
|
21
21
|
##
|
22
22
|
# Labels array.
|
23
|
-
|
23
|
+
|
24
24
|
attr_accessor :labels
|
25
|
-
|
25
|
+
|
26
26
|
##
|
27
27
|
# Issue number.
|
28
|
-
|
28
|
+
|
29
29
|
attr_accessor :number
|
30
|
-
|
30
|
+
|
31
31
|
##
|
32
32
|
# Initialize with _name_ and _options_.
|
33
|
-
|
33
|
+
|
34
34
|
def initialize name = nil, options = {}
|
35
35
|
super
|
36
36
|
options.each { |k,v| send :"#{k}=", v }
|
37
37
|
end
|
38
|
-
|
38
|
+
|
39
39
|
##
|
40
40
|
# Check if the task is a github issue.
|
41
|
-
|
41
|
+
|
42
42
|
def github?
|
43
43
|
true
|
44
44
|
end
|
45
|
-
|
45
|
+
|
46
46
|
##
|
47
47
|
# Absolute URI to github issue.
|
48
|
-
|
48
|
+
|
49
49
|
def uri
|
50
|
-
"
|
50
|
+
"https://github.com/#{username}/#{project}/issues#issue/#{number}"
|
51
51
|
end
|
52
|
-
|
52
|
+
|
53
53
|
end
|
54
|
-
end
|
54
|
+
end
|
data/lib/pomo/list.rb
CHANGED
@@ -1,26 +1,31 @@
|
|
1
1
|
|
2
2
|
module Pomo
|
3
3
|
class List
|
4
|
-
|
4
|
+
|
5
5
|
##
|
6
6
|
# List path.
|
7
|
-
|
7
|
+
|
8
8
|
attr_reader :path
|
9
|
-
|
9
|
+
|
10
10
|
##
|
11
11
|
# Task array.
|
12
|
-
|
12
|
+
|
13
13
|
attr_accessor :tasks
|
14
|
-
|
14
|
+
|
15
15
|
##
|
16
16
|
# Initialize with _path_.
|
17
|
-
|
18
|
-
def initialize
|
17
|
+
|
18
|
+
def initialize opts = {}
|
19
|
+
if opts[:init]
|
20
|
+
path = '.pomo'
|
21
|
+
else
|
22
|
+
path = File.exists?('.pomo') ? '.pomo' : File.join(ENV['HOME'],'.pomo')
|
23
|
+
end
|
19
24
|
@path = File.expand_path path
|
20
25
|
@tasks = []
|
21
26
|
load rescue save
|
22
27
|
end
|
23
|
-
|
28
|
+
|
24
29
|
##
|
25
30
|
# Find tasks by _args_, iterating with _block_.
|
26
31
|
#
|
@@ -36,7 +41,7 @@ module Pomo
|
|
36
41
|
# * complete[d]
|
37
42
|
# * all
|
38
43
|
#
|
39
|
-
|
44
|
+
|
40
45
|
def find *args, &block
|
41
46
|
found = []
|
42
47
|
found << tasks.first if args.empty?
|
@@ -54,39 +59,46 @@ module Pomo
|
|
54
59
|
found = tasks[$1.to_i..$2.to_i]
|
55
60
|
else
|
56
61
|
tasks.each_with_index do |task, i|
|
57
|
-
found << task if args.any? { |a| a.to_i == i }
|
62
|
+
found << task if args.any? { |a| a.to_i == i }
|
58
63
|
end
|
59
64
|
end
|
60
65
|
found.each_with_index do |task, i|
|
61
66
|
yield task, i
|
62
67
|
end
|
63
68
|
end
|
64
|
-
|
69
|
+
|
70
|
+
##
|
71
|
+
# Find currently running _task_ or nil.
|
72
|
+
|
73
|
+
def running
|
74
|
+
tasks.detect {|task| task.running? }
|
75
|
+
end
|
76
|
+
|
65
77
|
##
|
66
78
|
# Add _task_ to the list in memory (requires saving).
|
67
|
-
|
79
|
+
|
68
80
|
def add task
|
69
81
|
@tasks << task
|
70
82
|
end
|
71
83
|
alias :<< :add
|
72
|
-
|
84
|
+
|
73
85
|
##
|
74
86
|
# Save the list.
|
75
|
-
|
87
|
+
|
76
88
|
def save
|
77
89
|
File.open(path, 'w') do |file|
|
78
90
|
file.write YAML.dump(tasks)
|
79
91
|
end
|
80
92
|
self
|
81
93
|
end
|
82
|
-
|
94
|
+
|
83
95
|
##
|
84
96
|
# Load the list.
|
85
|
-
|
97
|
+
|
86
98
|
def load
|
87
99
|
@tasks = YAML.load_file path
|
88
100
|
self
|
89
101
|
end
|
90
|
-
|
102
|
+
|
91
103
|
end
|
92
|
-
end
|
104
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
|
2
|
+
module Pomo
|
3
|
+
class Notifier
|
4
|
+
|
5
|
+
##
|
6
|
+
# Initialize notifier library from configuration.
|
7
|
+
def initialize(config)
|
8
|
+
if config.notifier == 'notification_center'
|
9
|
+
@notifier = Pomo::Notifier::NotificationCenter.new
|
10
|
+
elsif config.notifier == 'libnotify'
|
11
|
+
@notifier = Pomo::Notifier::Growl.new
|
12
|
+
elsif config.notifier == 'growl'
|
13
|
+
@notifier = Pomo::Notifier::Libnotify.new
|
14
|
+
elsif config.notifier == 'quicksilver'
|
15
|
+
@notifier = Pomo::Notifier::Quicksilver.new
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
##
|
20
|
+
# Send message to notification library.
|
21
|
+
def notify(message, opts = {})
|
22
|
+
@notifier.notify(message, opts)
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
|
2
|
+
module Pomo
|
3
|
+
class Notifier
|
4
|
+
class Growl
|
5
|
+
def notify(message, opts = {})
|
6
|
+
full_message = [opts[:header], opts[:message]].join(' ').lstrip
|
7
|
+
|
8
|
+
if opts[:type].equal? :warning
|
9
|
+
Growl.notify_warning full_message
|
10
|
+
else
|
11
|
+
Growl.notify_info full_message
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
|
2
|
+
module Pomo
|
3
|
+
class Notifier
|
4
|
+
class Libnotify
|
5
|
+
def notify(message, opts = {})
|
6
|
+
title = 'Pomo'
|
7
|
+
full_message = [opts[:header], opts[:message]].join(' ').lstrip
|
8
|
+
|
9
|
+
Libnotify.show :body => full_message, :summary => title
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
14
|
+
end
|
data/lib/pomo/task.rb
CHANGED
@@ -1,75 +1,170 @@
|
|
1
1
|
|
2
2
|
module Pomo
|
3
3
|
class Task
|
4
|
-
|
5
|
-
#--
|
6
|
-
# Mixins
|
7
|
-
#++
|
8
|
-
|
9
|
-
include Growl
|
10
|
-
|
4
|
+
|
11
5
|
##
|
12
6
|
# Task name.
|
13
|
-
|
7
|
+
|
14
8
|
attr_accessor :name
|
15
|
-
|
9
|
+
|
16
10
|
##
|
17
11
|
# Length in minutes.
|
18
|
-
|
12
|
+
|
19
13
|
attr_accessor :length
|
20
|
-
|
14
|
+
|
21
15
|
##
|
22
16
|
# Verbose task description.
|
23
|
-
|
17
|
+
|
24
18
|
attr_accessor :description
|
25
|
-
|
19
|
+
|
20
|
+
##
|
21
|
+
# Task currently running bool.
|
22
|
+
|
23
|
+
attr_accessor :running
|
24
|
+
|
26
25
|
##
|
27
26
|
# Task completion bool.
|
28
|
-
|
27
|
+
|
29
28
|
attr_accessor :complete
|
30
|
-
|
29
|
+
|
31
30
|
##
|
32
31
|
# Initialize with _name_ and _options_.
|
33
|
-
|
32
|
+
|
34
33
|
def initialize name = nil, options = {}
|
35
34
|
@name = name or raise '<task> required'
|
36
35
|
@description = options.delete :description
|
37
36
|
@length = options.fetch :length, 25
|
37
|
+
@running = false
|
38
38
|
@complete = false
|
39
39
|
end
|
40
|
-
|
40
|
+
|
41
41
|
##
|
42
42
|
# Quoted task name.
|
43
|
-
|
43
|
+
|
44
44
|
def to_s
|
45
45
|
name.inspect
|
46
46
|
end
|
47
|
-
|
47
|
+
|
48
|
+
##
|
49
|
+
# Check if the task currently running.
|
50
|
+
|
51
|
+
def running?
|
52
|
+
running
|
53
|
+
end
|
54
|
+
|
48
55
|
##
|
49
56
|
# Check if the task has been completed.
|
50
|
-
|
57
|
+
|
51
58
|
def complete?
|
52
59
|
complete
|
53
60
|
end
|
54
|
-
|
61
|
+
|
55
62
|
##
|
56
63
|
# Start timing the task.
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
64
|
+
def start(config, options = {})
|
65
|
+
list = options[:list]
|
66
|
+
progress = options[:progress]
|
67
|
+
|
68
|
+
@running = true
|
69
|
+
list.save unless list.nil?
|
70
|
+
|
71
|
+
if progress
|
72
|
+
foreground_progress(config)
|
73
|
+
else
|
74
|
+
background_progress(config)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
private
|
79
|
+
|
80
|
+
def foreground_progress(config)
|
81
|
+
notifier = Pomo::Notifier.new(config)
|
82
|
+
|
83
|
+
say "Started #{self}, you have #{length} minutes :)"
|
84
|
+
|
85
|
+
complete_message = "Time is up! Hope you are finished #{self}"
|
86
|
+
format_message = '(:progress_bar) :remaining minutes remaining'
|
87
|
+
progress(
|
88
|
+
(0..length).to_a.reverse,
|
89
|
+
:format => format_message,
|
90
|
+
:tokens => { :remaining => length },
|
91
|
+
:complete_message => complete_message
|
92
|
+
) do |remaining|
|
62
93
|
if remaining == length / 2
|
63
|
-
|
94
|
+
notifier.notify 'Half way there!', :header => "#{remaining} minutes remaining"
|
64
95
|
elsif remaining == 5
|
65
|
-
|
96
|
+
notifier.notify 'Almost there!', :header => '5 minutes remaining'
|
66
97
|
end
|
67
98
|
sleep 60
|
68
99
|
{ :remaining => remaining }
|
69
100
|
end
|
70
|
-
|
71
|
-
|
101
|
+
|
102
|
+
notifier.notify "Hope you are finished #{self}", :header => 'Time is up!', :type => :warning
|
103
|
+
|
104
|
+
list = Pomo::List.new
|
105
|
+
if task = list.running
|
106
|
+
task.running = false
|
107
|
+
task.complete = true
|
108
|
+
list.save
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def background_progress(config)
|
113
|
+
notifier = Pomo::Notifier.new(config)
|
114
|
+
|
115
|
+
notifier.notify "Started #{self}", :header => "You have #{length} minutes"
|
116
|
+
|
117
|
+
pid = Process.fork do
|
118
|
+
length.downto(1) do |remaining|
|
119
|
+
write_tmux_time(remaining) if config.tmux
|
120
|
+
refresh_tmux_status_bar if config.tmux
|
121
|
+
if remaining == length / 2
|
122
|
+
notifier.notify 'Half way there!', :header => "#{remaining} minutes remaining"
|
123
|
+
elsif remaining == 5
|
124
|
+
notifier.notify 'Almost there!', :header => '5 minutes remaining'
|
125
|
+
end
|
126
|
+
sleep 60
|
127
|
+
end
|
128
|
+
|
129
|
+
write_tmux_time(0) if config.tmux
|
130
|
+
refresh_tmux_status_bar if config.tmux
|
131
|
+
notifier.notify "Hope you are finished #{self}", :header => 'Time is up!', :type => :warning
|
132
|
+
|
133
|
+
list = Pomo::List.new
|
134
|
+
if task = list.running
|
135
|
+
task.running = false
|
136
|
+
task.complete = true
|
137
|
+
list.save
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
Process.detach(pid)
|
72
142
|
end
|
73
|
-
|
143
|
+
|
144
|
+
def tmux_time(time)
|
145
|
+
case time
|
146
|
+
when 0
|
147
|
+
"#{time}:00"
|
148
|
+
when 1..5
|
149
|
+
"#[default]#[fg=red]#{time}:00#[default]"
|
150
|
+
when 6..00
|
151
|
+
"#[default]#[fg=green]#{time}:00#[default]"
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
def write_tmux_time(time)
|
156
|
+
path = File.join(ENV['HOME'],'.pomo_stat')
|
157
|
+
File.open(path, 'w') do |file|
|
158
|
+
file.write tmux_time(time)
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
def refresh_tmux_status_bar
|
163
|
+
pid = Process.fork do
|
164
|
+
exec "tmux refresh-client -S -t $(tmux list-clients -F '\#{client_tty}')"
|
165
|
+
end
|
166
|
+
Process.detach(pid)
|
167
|
+
end
|
168
|
+
|
74
169
|
end
|
75
|
-
end
|
170
|
+
end
|