popro 0.1.1 → 0.2.2
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.
- 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
|
+
[](https://badge.fury.io/rb/popro)
|
4
|
+
[](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: []
|