popro 0.1.1 → 0.2.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG +3 -0
- data/README.md +13 -6
- data/lib/popro.rb +5 -2
- data/lib/popro/context.rb +15 -3
- data/lib/popro/formatter.rb +48 -1
- data/lib/popro/indicator.rb +20 -4
- data/lib/popro/progress.rb +25 -6
- metadata +7 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a790befdf497a693172bb0faf40561c1d7fd6e287a3b5c379f7ddd9496f33509
|
4
|
+
data.tar.gz: a015de37abef0c5769a5d786182319fb891e874124daa5503a7feb9b411438fe
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0a2b3c066fe0a666537e40a2d63b81442e463c4b421a29d67722ad364453695fe17ea247a66c8d2e695e389b1482b56788dc03efff8836821a63f61d0592a5dd
|
7
|
+
data.tar.gz: 87151aae4f7c3ac0650960e5fdf646d4a373742dec759e3872fb8ea3be96c5b64b585401e6b6897c57ed7c86ed23987f1d33f426ffafbabf8e50558348046d3f
|
data/CHANGELOG
CHANGED
data/README.md
CHANGED
@@ -1,13 +1,20 @@
|
|
1
1
|
# Po'Pro: The Poor-Man's Progress Indicator
|
2
2
|
|
3
|
+
[![Version](https://badge.fury.io/rb/popro.svg)](https://badge.fury.io/rb/popro)
|
4
|
+
[![Tests](https://github.com/MikeSmithEU/PoPro/workflows/Code%20quality%20&%20unit%20tests/badge.svg)](https://github.com/MikeSmithEU/PoPro/actions?query=workflow%3A%22Code+quality+%26+unit+tests%22)
|
5
|
+
|
6
|
+
## Current TODOs
|
7
|
+
|
8
|
+
- [ ] properly update documentation
|
9
|
+
- [ ] simplify some stuff (each0?)
|
10
|
+
- [ ] 100% code coverage
|
11
|
+
|
3
12
|
## Why?
|
4
13
|
|
5
14
|
Easier and cleaner progress indication.
|
6
15
|
|
7
16
|
## How?
|
8
17
|
|
9
|
-
TODO: properly update documentation, simplify some stuff. 100% code coverage
|
10
|
-
|
11
18
|
### Basic usage
|
12
19
|
|
13
20
|
The invocation `Popro#did(yielded)` is used to signify that one step in progress has been finished.
|
@@ -263,11 +270,11 @@ end
|
|
263
270
|
## Formatters
|
264
271
|
|
265
272
|
You can set your own formatters using `Popro#formatter(&block)`. Each formatter can be a `Proc`, `block` or
|
266
|
-
class implementing the `call` method (e.g. the `
|
273
|
+
class implementing the `call` method (e.g. the `Popro::Formatter::*` classes).
|
267
274
|
|
268
275
|
The formatter will be invoked with 2 arguments:
|
269
276
|
|
270
|
-
1. `info`, an instance of `
|
277
|
+
1. `info`, an instance of `Popro::Info` containing e.g. `current` and `total`.
|
271
278
|
2. `yielded`, whatever was passed to the `Popro#did` method.
|
272
279
|
|
273
280
|
It can also be used inside blocks.
|
@@ -315,7 +322,7 @@ would output:
|
|
315
322
|
|
316
323
|
Indicator classes are responsible for communicating the progress (or not, as the case may be).
|
317
324
|
|
318
|
-
It is possible to provide your own "indicators" or use one of the provided ones (see `
|
325
|
+
It is possible to provide your own "indicators" or use one of the provided ones (see `Popro::Indicator` module).
|
319
326
|
|
320
|
-
The default `
|
327
|
+
The default `Popro::Indicator` class is `Popro::Indicator.default` (which returns an instance of `Popro::Indicator::Stream`), which outputs the progress to STDOUT each time `Popro#did` or `Popro#will` is called.
|
321
328
|
|
data/lib/popro.rb
CHANGED
@@ -7,7 +7,7 @@ module Popro
|
|
7
7
|
|
8
8
|
require_relative 'popro/progress'
|
9
9
|
|
10
|
-
def self.new(total, **options, &block)
|
10
|
+
def self.new(total = 0, **options, &block)
|
11
11
|
raise ConfigError, 'using :total is not supported in new' if options.key?(:total) && (options[:total] != total)
|
12
12
|
|
13
13
|
options[:total] = total
|
@@ -15,7 +15,6 @@ module Popro
|
|
15
15
|
end
|
16
16
|
|
17
17
|
def self.each(obj, total = nil, **options, &block)
|
18
|
-
options[:step] = 0 unless options.key? :step
|
19
18
|
new(0, **options).each(obj, total, &block).done
|
20
19
|
end
|
21
20
|
|
@@ -23,6 +22,10 @@ module Popro
|
|
23
22
|
new(0, **options).each_will(obj, titler, total, &block).done
|
24
23
|
end
|
25
24
|
|
25
|
+
def self.each_gonna(obj, titler, total = nil, **options, &block)
|
26
|
+
new(0, **options).each_gonna(obj, titler, total, &block).done
|
27
|
+
end
|
28
|
+
|
26
29
|
def self.command_line(*_args)
|
27
30
|
raise 'TODO: implement a `ps` style progress indicator for command line'
|
28
31
|
end
|
data/lib/popro/context.rb
CHANGED
@@ -54,7 +54,7 @@ module Popro
|
|
54
54
|
def did(yielded = nil, amount = nil)
|
55
55
|
@info.start unless @info.running?
|
56
56
|
amount = @step if amount.nil?
|
57
|
-
raise TypeError
|
57
|
+
raise TypeError, "amount: expected an integer, got #{amount.class}" unless amount.is_a? Integer
|
58
58
|
|
59
59
|
@info.current += amount unless amount.zero?
|
60
60
|
@indicator.call(@info, yielded)
|
@@ -62,8 +62,20 @@ module Popro
|
|
62
62
|
self
|
63
63
|
end
|
64
64
|
|
65
|
+
def gonna(title)
|
66
|
+
@indicator.call(@info, title)
|
67
|
+
self
|
68
|
+
end
|
69
|
+
|
70
|
+
def each_gonna(obj, titler, total = nil, &block)
|
71
|
+
_each(obj, total) do |*args|
|
72
|
+
gonna(titler.call(*args))
|
73
|
+
block.call(*args, progress: @info) if block_given?
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
65
77
|
def will(title = nil, step = nil, &block)
|
66
|
-
|
78
|
+
gonna "#{WILL_CHECK_MARKS[0]} #{title}"
|
67
79
|
|
68
80
|
return self unless block_given?
|
69
81
|
|
@@ -81,7 +93,7 @@ module Popro
|
|
81
93
|
|
82
94
|
def _each(obj, total = nil, &block)
|
83
95
|
total = obj.size if total.nil?
|
84
|
-
raise TypeError
|
96
|
+
raise TypeError, "total: expected an integer got #{total.class}" unless total.is_a?(Integer) || total.nil?
|
85
97
|
|
86
98
|
@info.total += total if total.positive?
|
87
99
|
# block = proc { |d| d } unless block_given?
|
data/lib/popro/formatter.rb
CHANGED
@@ -30,7 +30,7 @@ module Popro
|
|
30
30
|
def call(info, *args)
|
31
31
|
result = @formatter.call(info, *args)
|
32
32
|
@longest = [@longest, result.size].max
|
33
|
-
"\r
|
33
|
+
"\r#{result.ljust(@longest, ' ')}"
|
34
34
|
end
|
35
35
|
end
|
36
36
|
|
@@ -43,6 +43,53 @@ module Popro
|
|
43
43
|
end
|
44
44
|
end
|
45
45
|
|
46
|
+
class Estimate
|
47
|
+
# TODO: cleaner implementation/formatstring
|
48
|
+
attr_reader :info
|
49
|
+
|
50
|
+
def initialize
|
51
|
+
@start_time = current_time
|
52
|
+
@info = nil
|
53
|
+
end
|
54
|
+
|
55
|
+
def call(info, *_args)
|
56
|
+
@info = info
|
57
|
+
|
58
|
+
[
|
59
|
+
"estimated time left: #{format_duration(estimated_left)}",
|
60
|
+
"[#{format_duration(elapsed)}/#{format_duration(estimated_total)}]"
|
61
|
+
].join(', ')
|
62
|
+
end
|
63
|
+
|
64
|
+
private
|
65
|
+
|
66
|
+
def elapsed
|
67
|
+
current_time - @start_time
|
68
|
+
end
|
69
|
+
|
70
|
+
def estimated_total
|
71
|
+
return nil if info.current.zero? || info.total.zero?
|
72
|
+
|
73
|
+
elapsed + (info.total / info.current) * elapsed
|
74
|
+
end
|
75
|
+
|
76
|
+
def estimated_left
|
77
|
+
return nil if info.current.zero? || info.total.zero?
|
78
|
+
|
79
|
+
(info.total / info.current) * elapsed
|
80
|
+
end
|
81
|
+
|
82
|
+
def format_duration(secs)
|
83
|
+
return '??d??h??m??s' if secs.nil?
|
84
|
+
|
85
|
+
format('%02dd%02dh%02dm%02ds', secs / 86_400, secs / 3600 % 24, secs / 60 % 60, secs % 60)
|
86
|
+
end
|
87
|
+
|
88
|
+
def current_time
|
89
|
+
Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
46
93
|
class Sprintf
|
47
94
|
def initialize(format_string = nil)
|
48
95
|
@format_string = format_string
|
data/lib/popro/indicator.rb
CHANGED
@@ -27,7 +27,7 @@ module Popro
|
|
27
27
|
formatter = self.class.default_formatter(formatter) if formatter.nil? || formatter.is_a?(String)
|
28
28
|
|
29
29
|
@formatter = formatter
|
30
|
-
@stream = stream ||
|
30
|
+
@stream = stream || $stdout
|
31
31
|
end
|
32
32
|
|
33
33
|
def call(*args)
|
@@ -45,11 +45,27 @@ module Popro
|
|
45
45
|
end
|
46
46
|
end
|
47
47
|
|
48
|
-
|
48
|
+
class Callback
|
49
|
+
def initialize(finish = nil, &block)
|
50
|
+
@finish = finish
|
51
|
+
@callback = block
|
52
|
+
end
|
53
|
+
|
54
|
+
def call(*args)
|
55
|
+
@callback.call(*args)
|
56
|
+
end
|
57
|
+
|
58
|
+
def finish
|
59
|
+
@finish&.call
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def self.default_formatter(*extra_formatters)
|
49
64
|
::Popro::Formatter::RewriteLine.new(
|
50
65
|
::Popro::Formatter::Concat.new(
|
51
66
|
::Popro::Formatter::Spinner.new(:dots, bounce: true),
|
52
67
|
::Popro::Formatter::Sprintf.new,
|
68
|
+
*extra_formatters,
|
53
69
|
(proc do |_, yielded = nil|
|
54
70
|
yielded if yielded.is_a?(String) || yielded.is_a?(Numeric)
|
55
71
|
end),
|
@@ -58,8 +74,8 @@ module Popro
|
|
58
74
|
)
|
59
75
|
end
|
60
76
|
|
61
|
-
def self.default
|
62
|
-
Stream.new(formatter: default_formatter)
|
77
|
+
def self.default(*extra_formatters)
|
78
|
+
Stream.new(formatter: default_formatter(*extra_formatters))
|
63
79
|
end
|
64
80
|
end
|
65
81
|
end
|
data/lib/popro/progress.rb
CHANGED
@@ -6,17 +6,24 @@ module Popro
|
|
6
6
|
require_relative 'info'
|
7
7
|
require_relative 'indicator'
|
8
8
|
|
9
|
+
DEFAULT_OPTIONS ||= {
|
10
|
+
total: 0,
|
11
|
+
current: 0,
|
12
|
+
indicator: Indicator.default
|
13
|
+
}.freeze
|
14
|
+
|
9
15
|
attr_reader :context
|
10
16
|
|
11
17
|
def initialize(**options)
|
12
18
|
@started = false
|
13
|
-
@info = Info.new(total: options.delete(:total), current: options.delete(:current))
|
14
19
|
|
15
|
-
options
|
16
|
-
|
17
|
-
|
18
|
-
options[:indicator] = Indicator.default unless options.key? :indicator
|
20
|
+
options = DEFAULT_OPTIONS
|
21
|
+
.merge(step: block_given? ? 0 : 1)
|
22
|
+
.merge(options)
|
19
23
|
|
24
|
+
@info = Info.new(total: options.delete(:total), current: options.delete(:current))
|
25
|
+
|
26
|
+
options.merge!(progress: self, info: @info)
|
20
27
|
@context = Context.new(**options)
|
21
28
|
|
22
29
|
register_aliases
|
@@ -26,15 +33,27 @@ module Popro
|
|
26
33
|
done
|
27
34
|
end
|
28
35
|
|
36
|
+
# increase the total
|
37
|
+
def add(amount)
|
38
|
+
@info.total += amount
|
39
|
+
self
|
40
|
+
end
|
41
|
+
|
29
42
|
private
|
30
43
|
|
31
44
|
def register_aliases
|
32
45
|
class << self
|
33
|
-
%i[each each_will to_proc
|
46
|
+
%i[each each_will each_gonna to_proc gonna will did formatter start done].each do |method_name|
|
34
47
|
define_method method_name do |*args, &block|
|
35
48
|
@context.public_send(method_name, *args, &block)
|
36
49
|
end
|
37
50
|
end
|
51
|
+
|
52
|
+
%i[current total].each do |method_name|
|
53
|
+
define_method method_name do
|
54
|
+
@info.public_send(method_name)
|
55
|
+
end
|
56
|
+
end
|
38
57
|
end
|
39
58
|
end
|
40
59
|
end
|
metadata
CHANGED
@@ -1,17 +1,17 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: popro
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- MikeSmithEU
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-09-16 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: The Poor-Man's Progress Indicator
|
14
|
-
email:
|
14
|
+
email:
|
15
15
|
executables: []
|
16
16
|
extensions: []
|
17
17
|
extra_rdoc_files: []
|
@@ -31,7 +31,7 @@ homepage: https://rubygems.org/gems/popro
|
|
31
31
|
licenses:
|
32
32
|
- MIT
|
33
33
|
metadata: {}
|
34
|
-
post_install_message:
|
34
|
+
post_install_message:
|
35
35
|
rdoc_options: []
|
36
36
|
require_paths:
|
37
37
|
- lib
|
@@ -39,7 +39,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
39
39
|
requirements:
|
40
40
|
- - ">="
|
41
41
|
- !ruby/object:Gem::Version
|
42
|
-
version: '
|
42
|
+
version: '2.7'
|
43
43
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
45
|
- - ">="
|
@@ -47,7 +47,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
47
47
|
version: '0'
|
48
48
|
requirements: []
|
49
49
|
rubygems_version: 3.1.2
|
50
|
-
signing_key:
|
50
|
+
signing_key:
|
51
51
|
specification_version: 4
|
52
52
|
summary: Po'Pro
|
53
53
|
test_files: []
|