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/lib/pomo/break.rb ADDED
@@ -0,0 +1,17 @@
1
+
2
+ module Pomo
3
+ class Break < Task
4
+
5
+ private
6
+
7
+ def tmux_time(time)
8
+ case time
9
+ when 0
10
+ "#{time}:00"
11
+ else
12
+ "#[default]#[fg=blue]#{time}:00#[default]"
13
+ end
14
+ end
15
+
16
+ end
17
+ end
@@ -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
@@ -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
- "http://github.com/#{username}/#{project}/issues#issue/#{number}"
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 path
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
@@ -0,0 +1,13 @@
1
+
2
+ module Pomo
3
+ class Notifier
4
+ class NotificationCenter
5
+ def notify(message, opts = {})
6
+ title = 'Pomo'
7
+
8
+ TerminalNotifier.notify message, :title => title, :subtitle => opts[:header]
9
+ end
10
+ end
11
+
12
+ end
13
+ end
@@ -0,0 +1,12 @@
1
+
2
+ module Pomo
3
+ class Notifier
4
+ class Quicksilver
5
+ def notify(message, opts = {})
6
+ `osascript -e 'tell application "Quicksilver" to show large type "#{message.gsub('"', '\"')}"'`
7
+ end
8
+ end
9
+
10
+ end
11
+ end
12
+
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
- def start
59
- complete_message = "time is up! hope you are finished #{self}"
60
- format_message = "(:progress_bar) :remaining minutes remaining"
61
- progress (0..length).to_a.reverse, :format => format_message, :tokens => { :remaining => length }, :complete_message => complete_message do |remaining|
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
- notify_info "#{remaining} minutes remaining, half way there!"
94
+ notifier.notify 'Half way there!', :header => "#{remaining} minutes remaining"
64
95
  elsif remaining == 5
65
- notify_info "5 minutes remaining"
96
+ notifier.notify 'Almost there!', :header => '5 minutes remaining'
66
97
  end
67
98
  sleep 60
68
99
  { :remaining => remaining }
69
100
  end
70
- @complete = true
71
- notify_warning complete_message
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