prb 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +14 -3
- data/README.md +32 -16
- data/exe/prb +20 -9
- data/lib/prb.rb +6 -0
- data/lib/prb/command_runner.rb +22 -28
- data/lib/prb/opts.rb +16 -0
- data/lib/prb/server.rb +24 -60
- data/lib/prb/timer.rb +35 -19
- data/lib/prb/timer_control.rb +15 -24
- data/lib/prb/version.rb +1 -1
- data/prb.gemspec +2 -1
- metadata +21 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d09ffeecc26a41b306564b20a9e9acc62d5cbbfd9b03a16684ae0204f289717e
|
4
|
+
data.tar.gz: 0d6615043f85ff16ab3f4da9c5e2c5fa17525d16c6425b32d210898084683680
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d5c9433e04646ea3467add2f8915cdb2ccd6c2ecb8a1dfcd6118a46f42593b0db22ab0a210316b90de478a38939a401b9e80fabbe602c9dd20c49e2036fd58cd
|
7
|
+
data.tar.gz: 8836c99454be9f1cbaf3a1f63c1104c3437ed350b5db9abe656fc417ff2976be188052e1b4194f349851588b9e17e479f5396350a77da42c2f925d28d627a21b
|
data/Gemfile.lock
CHANGED
@@ -1,14 +1,19 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
prb (0.
|
5
|
-
optimist
|
4
|
+
prb (0.2.0)
|
5
|
+
optimist (~> 3.0)
|
6
|
+
sinatra (~> 2.0)
|
6
7
|
|
7
8
|
GEM
|
8
9
|
remote: https://rubygems.org/
|
9
10
|
specs:
|
10
11
|
diff-lcs (1.3)
|
12
|
+
mustermann (1.0.3)
|
11
13
|
optimist (3.0.0)
|
14
|
+
rack (2.0.7)
|
15
|
+
rack-protection (2.0.7)
|
16
|
+
rack
|
12
17
|
rake (10.5.0)
|
13
18
|
rspec (3.8.0)
|
14
19
|
rspec-core (~> 3.8.0)
|
@@ -23,6 +28,12 @@ GEM
|
|
23
28
|
diff-lcs (>= 1.2.0, < 2.0)
|
24
29
|
rspec-support (~> 3.8.0)
|
25
30
|
rspec-support (3.8.0)
|
31
|
+
sinatra (2.0.7)
|
32
|
+
mustermann (~> 1.0)
|
33
|
+
rack (~> 2.0)
|
34
|
+
rack-protection (= 2.0.7)
|
35
|
+
tilt (~> 2.0)
|
36
|
+
tilt (2.0.10)
|
26
37
|
|
27
38
|
PLATFORMS
|
28
39
|
ruby
|
@@ -34,4 +45,4 @@ DEPENDENCIES
|
|
34
45
|
rspec (~> 3.0)
|
35
46
|
|
36
47
|
BUNDLED WITH
|
37
|
-
2.0.
|
48
|
+
2.0.2
|
data/README.md
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# Prb
|
2
2
|
|
3
|
-
|
4
|
-
|
3
|
+
Prb is a light-weight HTTP service written in Ruby for controlling a pomodoro
|
4
|
+
timer.
|
5
5
|
|
6
6
|
## Installation
|
7
7
|
|
@@ -11,24 +11,40 @@ Install the gem
|
|
11
11
|
|
12
12
|
## Usage
|
13
13
|
|
14
|
+
The promodoro timer can be started using `prb start -d` where `-d` will
|
15
|
+
run the process in the background.
|
16
|
+
|
17
|
+
```
|
18
|
+
prb start -d
|
19
|
+
```
|
20
|
+
|
21
|
+
Options can be passed to configure the timer. By default, there are 4 pomodoro's
|
22
|
+
each taking 25 minutes to complete. You can override this behaviour using the
|
23
|
+
following command:
|
24
|
+
|
25
|
+
```
|
26
|
+
prb start -d --pomodoros=4 --timer=25
|
14
27
|
```
|
15
|
-
prb v0.1.0 - Pomodoro timer service
|
16
28
|
|
17
|
-
|
18
|
-
|
29
|
+
After starting the service you can query the timers status over HTTP using
|
30
|
+
`curl`:
|
19
31
|
|
20
|
-
|
21
|
-
|
32
|
+
```
|
33
|
+
curl http://localhost:3838/status
|
34
|
+
|
35
|
+
{
|
36
|
+
"running" true,
|
37
|
+
"completed": 0, # completed pomodoros
|
38
|
+
"remaining": 4, # remaining pomodoros
|
39
|
+
"time_remaining": 440
|
40
|
+
}
|
41
|
+
```
|
22
42
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
reset Reset the current timer
|
29
|
-
pause Pause the current timer
|
30
|
-
-v, --version Print version and exit
|
31
|
-
-h, --help Show this message
|
43
|
+
After each pomodoro the timer will stop. The timer can be resumed
|
44
|
+
and the next pomodoro started by using `prb resume` or by `curl` request:
|
45
|
+
|
46
|
+
```
|
47
|
+
curl http://localhost:3838/resume
|
32
48
|
```
|
33
49
|
|
34
50
|
## Development
|
data/exe/prb
CHANGED
@@ -1,31 +1,42 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
3
|
require "optimist"
|
4
|
+
require "webrick"
|
4
5
|
require "bundler/setup"
|
5
6
|
require "prb"
|
6
7
|
|
7
8
|
COMMAND_MAP = {
|
8
9
|
'start' => 'Start pomodoro service',
|
9
|
-
'
|
10
|
-
'
|
11
|
-
'skip' => 'Skip the current timer',
|
12
|
-
'reset' => 'Reset the current timer',
|
13
|
-
'pause' => 'Pause the current timer'
|
10
|
+
'resume' => 'Resume pomodoro timer',
|
11
|
+
'stop' => 'Stop pomodoro service'
|
14
12
|
}
|
15
13
|
|
16
|
-
|
14
|
+
global_opts = Optimist::options do
|
17
15
|
version "prb v#{Prb::VERSION}"
|
18
16
|
banner "prb v#{Prb::VERSION} - Pomodoro timer service\n \n"
|
19
17
|
banner "Usage:"
|
20
|
-
banner " prb [COMMAND] [SUB_COMMAND]\n
|
21
|
-
banner "Options:"
|
22
|
-
opt :daemonize, 'Start the service in the background', short: '-d'
|
18
|
+
banner " prb [COMMAND] [SUB_COMMAND]\n"
|
23
19
|
banner "\nCommands:"
|
24
20
|
COMMAND_MAP.each { |cmd, desc| banner format(" %-10s %s", cmd, desc) }
|
21
|
+
|
22
|
+
stop_on COMMAND_MAP.keys
|
25
23
|
end
|
26
24
|
|
27
25
|
commands = COMMAND_MAP.keys & ARGV
|
28
26
|
cmd = commands.first
|
27
|
+
opts = {}
|
28
|
+
|
29
|
+
case cmd
|
30
|
+
when "start"
|
31
|
+
opts = Optimist::options do
|
32
|
+
opt :pomodoros, "Number of pomodoros", default: 4
|
33
|
+
opt :timer, "The time in minutes for the timer", default: 25
|
34
|
+
opt :port, "The port to run the pomodoro HTTP server", default: 3838
|
35
|
+
opt :daemonize, 'Start the service in the background', short: '-d'
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
opts = opts.merge(global_opts)
|
29
40
|
|
30
41
|
if COMMAND_MAP.keys.include?(cmd)
|
31
42
|
Prb::CommandRunner.new(opts).send(cmd)
|
data/lib/prb.rb
CHANGED
data/lib/prb/command_runner.rb
CHANGED
@@ -1,57 +1,51 @@
|
|
1
1
|
module Prb
|
2
2
|
class CommandRunner
|
3
3
|
def initialize(opts)
|
4
|
-
@opts = opts
|
4
|
+
@opts = Opts.new(opts)
|
5
5
|
end
|
6
6
|
|
7
7
|
def start
|
8
|
-
if
|
8
|
+
if running?(@opts.port)
|
9
9
|
puts "A prb server is already running."
|
10
10
|
exit(1)
|
11
11
|
end
|
12
12
|
|
13
|
-
Process.daemon() if @opts
|
13
|
+
Process.daemon() if @opts.daemonize?
|
14
14
|
|
15
|
-
Prb::Server.new
|
15
|
+
app = Prb::Server.new(@opts)
|
16
|
+
Rack::Server.start(
|
17
|
+
app: app,
|
18
|
+
Port: @opts.port
|
19
|
+
)
|
16
20
|
end
|
17
21
|
|
18
|
-
def
|
19
|
-
|
20
|
-
puts response
|
21
|
-
end
|
22
|
-
|
23
|
-
def skip
|
24
|
-
send_command('SKIP')
|
25
|
-
end
|
26
|
-
|
27
|
-
def pause
|
28
|
-
send_command('PAUSE')
|
29
|
-
end
|
30
|
-
|
31
|
-
def reset
|
32
|
-
send_command('RESET')
|
22
|
+
def resume
|
23
|
+
send_request('resume')
|
33
24
|
end
|
34
25
|
|
35
26
|
def stop
|
36
|
-
|
27
|
+
send_request('stop')
|
37
28
|
end
|
38
29
|
|
39
30
|
private
|
40
31
|
|
41
|
-
def
|
32
|
+
def send_request(endpoint)
|
33
|
+
uri = URI.parse("http://0.0.0.0:#{@opts.port}/#{endpoint}")
|
34
|
+
Net::HTTP.get_response(uri)
|
35
|
+
rescue
|
36
|
+
nil
|
37
|
+
end
|
38
|
+
|
39
|
+
def running?(port)
|
42
40
|
Timeout::timeout(1) do
|
43
41
|
begin
|
44
|
-
s = TCPSocket.new('
|
45
|
-
s.puts(cmd)
|
46
|
-
response = s.gets.chomp
|
42
|
+
s = TCPSocket.new('0.0.0.0', port)
|
47
43
|
s.close
|
48
|
-
return
|
44
|
+
return true
|
49
45
|
rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH
|
50
|
-
|
51
|
-
exit(1)
|
46
|
+
return false
|
52
47
|
end
|
53
48
|
end
|
54
49
|
end
|
55
50
|
end
|
56
|
-
|
57
51
|
end
|
data/lib/prb/opts.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
module Prb
|
2
|
+
class Opts
|
3
|
+
attr_reader :pomodoros, :timer, :port
|
4
|
+
|
5
|
+
def initialize(opts)
|
6
|
+
@pomodoros = opts[:pomodoros].to_i
|
7
|
+
@timer = opts[:timer].to_i
|
8
|
+
@daemonize = opts[:daemonize]
|
9
|
+
@port = (opts[:port] || 3838).to_i
|
10
|
+
end
|
11
|
+
|
12
|
+
def daemonize?
|
13
|
+
!!@daemonize
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
data/lib/prb/server.rb
CHANGED
@@ -1,76 +1,40 @@
|
|
1
|
-
require 'socket'
|
2
1
|
require 'timeout'
|
2
|
+
require 'sinatra/base'
|
3
3
|
|
4
4
|
module Prb
|
5
|
-
|
5
|
+
class Server < Sinatra::Base
|
6
|
+
def initialize(opts)
|
7
|
+
puts <<~MSG
|
8
|
+
Starting pomodoro service...
|
6
9
|
|
7
|
-
|
8
|
-
|
9
|
-
@controller = TimerControl.new
|
10
|
-
end
|
11
|
-
|
12
|
-
def start
|
13
|
-
@controller.start
|
14
|
-
|
15
|
-
server = TCPServer.open('127.0.0.1', PRB_PORT)
|
16
|
-
puts "Server listening on #{PRB_PORT}"
|
10
|
+
Number of pomodoros: #{opts.pomodoros} pomodoro(s)
|
11
|
+
Pomodoro timer: #{opts.timer} minute(s)
|
17
12
|
|
18
|
-
|
19
|
-
Thread.start(server.accept) do |socket|
|
20
|
-
while cmd = socket.gets.chomp
|
21
|
-
puts "RECV: #{cmd}"
|
13
|
+
MSG
|
22
14
|
|
23
|
-
|
24
|
-
|
25
|
-
when 'STATUS'
|
26
|
-
output = status_line
|
27
|
-
when 'SKIP'
|
28
|
-
@controller.toggle
|
29
|
-
when 'RESET'
|
30
|
-
@controller.reset
|
31
|
-
when 'PAUSE'
|
32
|
-
@controller.pause
|
33
|
-
when 'QUIT'
|
34
|
-
socket.puts "OK"
|
35
|
-
exit(0)
|
36
|
-
else
|
37
|
-
puts "ERR: #{cmd} not a command"
|
38
|
-
output = "ERR: #{cmd} not a command"
|
39
|
-
end
|
40
|
-
|
41
|
-
socket.puts output
|
42
|
-
end
|
15
|
+
@controller = TimerControl.new(opts)
|
16
|
+
@controller.start
|
43
17
|
|
44
|
-
|
45
|
-
|
46
|
-
end
|
18
|
+
super
|
19
|
+
end
|
47
20
|
|
48
|
-
|
21
|
+
get '/status' do
|
22
|
+
content_type :json
|
23
|
+
@controller.render_status
|
49
24
|
end
|
50
25
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
s = TCPSocket.new('127.0.0.1', PRB_PORT)
|
55
|
-
s.close
|
56
|
-
return true
|
57
|
-
rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH
|
58
|
-
return false
|
59
|
-
end
|
60
|
-
end
|
26
|
+
get '/reset' do
|
27
|
+
@controller.reset
|
28
|
+
status 200
|
61
29
|
end
|
62
30
|
|
63
|
-
|
31
|
+
get '/resume' do
|
32
|
+
@controller.resume
|
33
|
+
status 200
|
34
|
+
end
|
64
35
|
|
65
|
-
|
66
|
-
|
67
|
-
status << @controller.timer.render
|
68
|
-
status << ","
|
69
|
-
status << "WORKING" if @controller.is_working?
|
70
|
-
status << "BREAK" if !@controller.is_working?
|
71
|
-
status << ",PAUSED" if @controller.paused?
|
72
|
-
status << ",RUNNING" if !@controller.paused?
|
73
|
-
status
|
36
|
+
get '/stop' do
|
37
|
+
Process.kill("INT", Process.pid)
|
74
38
|
end
|
75
39
|
end
|
76
40
|
end
|
data/lib/prb/timer.rb
CHANGED
@@ -1,41 +1,57 @@
|
|
1
1
|
module Prb
|
2
2
|
class Timer
|
3
|
-
|
3
|
+
attr_reader :pomodoros, :seconds, :paused, :completed
|
4
|
+
|
5
|
+
WORKING = 1
|
6
|
+
PAUSED = 2
|
7
|
+
|
8
|
+
def initialize(opts)
|
9
|
+
@opts = opts
|
10
|
+
|
4
11
|
@paused = false
|
5
|
-
|
6
|
-
end
|
12
|
+
@pomodoros = opts.pomodoros
|
7
13
|
|
8
|
-
|
9
|
-
@
|
10
|
-
@seconds = @_seconds
|
14
|
+
# set pomodoro timer
|
15
|
+
set_timer(@opts.timer)
|
11
16
|
end
|
12
17
|
|
13
18
|
def tick
|
14
|
-
|
15
|
-
@seconds -= 1 unless @paused or finished?
|
16
|
-
end
|
19
|
+
return if completed? or paused?
|
17
20
|
|
18
|
-
|
19
|
-
|
21
|
+
if @seconds == 0
|
22
|
+
if @paused == false
|
23
|
+
@pomodoros -= 1
|
24
|
+
@paused = true
|
25
|
+
end
|
26
|
+
else
|
27
|
+
@seconds -= 1
|
28
|
+
end
|
20
29
|
end
|
21
30
|
|
22
|
-
def
|
23
|
-
@
|
31
|
+
def resume
|
32
|
+
@paused = false
|
33
|
+
set_timer(@opts.timer)
|
24
34
|
end
|
25
35
|
|
26
|
-
def
|
27
|
-
@paused =
|
36
|
+
def reset
|
37
|
+
@paused = false
|
38
|
+
@pomodoros = @opts.pomodoros
|
39
|
+
set_timer(@opts.timer)
|
28
40
|
end
|
29
41
|
|
30
42
|
def paused?
|
31
43
|
@paused
|
32
44
|
end
|
33
45
|
|
34
|
-
|
35
|
-
|
36
|
-
|
46
|
+
private
|
47
|
+
|
48
|
+
def set_timer(minutes)
|
49
|
+
@_seconds = minutes * 60
|
50
|
+
@seconds = @_seconds
|
51
|
+
end
|
37
52
|
|
38
|
-
|
53
|
+
def completed?
|
54
|
+
@pomodoros == 0
|
39
55
|
end
|
40
56
|
end
|
41
57
|
end
|
data/lib/prb/timer_control.rb
CHANGED
@@ -1,45 +1,36 @@
|
|
1
1
|
module Prb
|
2
2
|
class TimerControl
|
3
|
-
WORK_MINUTES = 25
|
4
|
-
BREAK_MINUTES = 5
|
5
|
-
|
6
3
|
attr_reader :timer
|
7
4
|
|
8
|
-
def initialize
|
9
|
-
@
|
10
|
-
@
|
5
|
+
def initialize(opts)
|
6
|
+
@opts = opts
|
7
|
+
@timer = Timer.new(@opts)
|
11
8
|
end
|
12
9
|
|
13
10
|
def start
|
14
11
|
Thread.new do
|
15
12
|
loop do
|
13
|
+
sleep 1
|
16
14
|
@timer.tick
|
17
|
-
toggle if @timer.finished?
|
18
15
|
end
|
19
16
|
end
|
20
17
|
end
|
21
18
|
|
22
|
-
def
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
19
|
+
def render_status
|
20
|
+
{
|
21
|
+
running: !@timer.paused?,
|
22
|
+
completed: @opts.pomodoros - @timer.pomodoros,
|
23
|
+
remaining: @timer.pomodoros,
|
24
|
+
time_remaining: @timer.seconds,
|
25
|
+
}.to_json
|
28
26
|
end
|
29
27
|
|
30
|
-
def
|
31
|
-
@timer.
|
32
|
-
end
|
33
|
-
|
34
|
-
def is_working?
|
35
|
-
@is_working
|
28
|
+
def reset
|
29
|
+
@timer.reset
|
36
30
|
end
|
37
31
|
|
38
|
-
def
|
39
|
-
@
|
40
|
-
@timer.set_timer(@is_working ?
|
41
|
-
WORK_MINUTES : BREAK_MINUTES)
|
42
|
-
@timer.pause unless @timer.paused?
|
32
|
+
def resume
|
33
|
+
@timer.resume
|
43
34
|
end
|
44
35
|
end
|
45
36
|
end
|
data/lib/prb/version.rb
CHANGED
data/prb.gemspec
CHANGED
@@ -36,7 +36,8 @@ Gem::Specification.new do |spec|
|
|
36
36
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
37
37
|
spec.require_paths = ["lib"]
|
38
38
|
|
39
|
-
spec.add_dependency "optimist"
|
39
|
+
spec.add_dependency "optimist", "~> 3.0"
|
40
|
+
spec.add_dependency "sinatra", "~> 2.0"
|
40
41
|
|
41
42
|
spec.add_development_dependency "bundler", "~> 2.0"
|
42
43
|
spec.add_development_dependency "rake", "~> 10.0"
|
metadata
CHANGED
@@ -1,29 +1,43 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: prb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Richard Ramsden
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
11
|
+
date: 2019-11-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: optimist
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '0'
|
19
|
+
version: '3.0'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - "
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '3.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: sinatra
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
25
32
|
- !ruby/object:Gem::Version
|
26
|
-
version: '0'
|
33
|
+
version: '2.0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '2.0'
|
27
41
|
- !ruby/object:Gem::Dependency
|
28
42
|
name: bundler
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -86,6 +100,7 @@ files:
|
|
86
100
|
- exe/prb
|
87
101
|
- lib/prb.rb
|
88
102
|
- lib/prb/command_runner.rb
|
103
|
+
- lib/prb/opts.rb
|
89
104
|
- lib/prb/server.rb
|
90
105
|
- lib/prb/timer.rb
|
91
106
|
- lib/prb/timer_control.rb
|