pomo 1.0.1 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
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