popro 0.0.1 → 0.2.1
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 +2 -0
- data/README.md +13 -6
- data/lib/popro.rb +4 -7
- data/lib/popro/context.rb +31 -32
- data/lib/popro/formatter.rb +48 -1
- data/lib/popro/indicator.rb +5 -4
- data/lib/popro/info.rb +0 -1
- 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: 28d2afab9d53f8fa8ebf80ec36ee2d0e1529d150a6ffd2993409ba845a3f4c79
|
4
|
+
data.tar.gz: 858dbf273be5fe62af6f0c74fbcfe51fd34f6491b344381f40fab71a053c50a1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 337b2b031a41c3ba78e438b906fac942b98eaacff1e0c489d01e4811b5f676760cc8e0b9f2d6fbab27c1ec344c5f42d6c677546ce7fb43d52a17f89d0d38ac98
|
7
|
+
data.tar.gz: 5d3b42ff7fb6ee26873afc35217daeb43b9f431f05e251c59e3b112ab13f14481fc0f0d108d3f3cb53f3c458a531af5ca55c5821f058d5941949bc59a0eeae51
|
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,22 +7,19 @@ 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
|
14
14
|
Progress.new(**options, &block)
|
15
15
|
end
|
16
16
|
|
17
|
-
def self.each(obj,
|
17
|
+
def self.each(obj, total = nil, **options, &block)
|
18
18
|
new(0, **options).each(obj, total, &block).done
|
19
19
|
end
|
20
20
|
|
21
|
-
def self.
|
22
|
-
|
23
|
-
|
24
|
-
options[:step] = 0
|
25
|
-
each(obj, 0, **options, &block)
|
21
|
+
def self.each_will(obj, titler, total = nil, **options, &block)
|
22
|
+
new(0, **options).each_will(obj, titler, total, &block).done
|
26
23
|
end
|
27
24
|
|
28
25
|
def self.command_line(*_args)
|
data/lib/popro/context.rb
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
module Popro
|
4
4
|
# the progress context passed as first argument to blocks (or named argument for `Progress#each` and `Popro.each`)
|
5
5
|
|
6
|
-
WILL_CHECK_MARKS ||= '
|
6
|
+
WILL_CHECK_MARKS ||= ' ✔'
|
7
7
|
|
8
8
|
class Context
|
9
9
|
def initialize(progress:, info:, indicator:, step: 1)
|
@@ -14,25 +14,17 @@ module Popro
|
|
14
14
|
end
|
15
15
|
|
16
16
|
def each(obj, total = nil, &block)
|
17
|
-
total
|
18
|
-
|
19
|
-
block = proc { |d| d } unless block_given?
|
20
|
-
|
21
|
-
obj.each do |*args|
|
22
|
-
did block.call(*args, progress: self)
|
17
|
+
_each(obj, total) do |*args|
|
18
|
+
did block.call(*args, progress: @info)
|
23
19
|
end
|
24
|
-
|
25
|
-
self
|
26
20
|
end
|
27
21
|
|
28
|
-
def
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
kwargs[:progress].will titler.call(*args) do
|
35
|
-
yield(*args, **kwargs)
|
22
|
+
def each_will(obj, titler, total = nil, &block)
|
23
|
+
_each(obj, total) do |*args|
|
24
|
+
title = titler.call(*args)
|
25
|
+
will(title) do
|
26
|
+
block.call(*args, progress: @info)
|
27
|
+
nil
|
36
28
|
end
|
37
29
|
end
|
38
30
|
end
|
@@ -59,25 +51,25 @@ module Popro
|
|
59
51
|
block
|
60
52
|
end
|
61
53
|
|
62
|
-
def did(yielded = nil, amount =
|
54
|
+
def did(yielded = nil, amount = nil)
|
63
55
|
@info.start unless @info.running?
|
64
|
-
|
56
|
+
amount = @step if amount.nil?
|
57
|
+
raise TypeError, "amount: expected an integer, got #{amount.class}" unless amount.is_a? Integer
|
58
|
+
|
59
|
+
@info.current += amount unless amount.zero?
|
60
|
+
@indicator.call(@info, yielded)
|
65
61
|
|
66
62
|
self
|
67
63
|
end
|
68
64
|
|
69
|
-
def will(title = nil,
|
70
|
-
|
71
|
-
inc 0, "#{WILL_CHECK_MARKS[0]} #{title}"
|
65
|
+
def will(title = nil, step = nil, &block)
|
66
|
+
did "#{WILL_CHECK_MARKS[0]} #{title}", 0
|
72
67
|
|
73
68
|
return self unless block_given?
|
74
69
|
|
75
|
-
|
76
|
-
yielded =
|
77
|
-
yielded
|
78
|
-
|
79
|
-
# no need to communicate to Indicator if we are not advancing (avoid double calls)
|
80
|
-
did yielded, step unless step.zero?
|
70
|
+
block.call
|
71
|
+
yielded = "#{WILL_CHECK_MARKS[1]} #{title}"
|
72
|
+
did(yielded, step || @step)
|
81
73
|
yielded
|
82
74
|
end
|
83
75
|
|
@@ -87,11 +79,18 @@ module Popro
|
|
87
79
|
|
88
80
|
private
|
89
81
|
|
90
|
-
def
|
91
|
-
|
82
|
+
def _each(obj, total = nil, &block)
|
83
|
+
total = obj.size if total.nil?
|
84
|
+
raise TypeError, "total: expected an integer got #{total.class}" unless total.is_a?(Integer) || total.nil?
|
92
85
|
|
93
|
-
@info.
|
94
|
-
|
86
|
+
@info.total += total if total.positive?
|
87
|
+
# block = proc { |d| d } unless block_given?
|
88
|
+
|
89
|
+
obj.each do |*args, **kwargs|
|
90
|
+
block.call(*args, **kwargs)
|
91
|
+
end
|
92
|
+
|
93
|
+
self
|
95
94
|
end
|
96
95
|
end
|
97
96
|
end
|
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,12 @@ module Popro
|
|
45
45
|
end
|
46
46
|
end
|
47
47
|
|
48
|
-
def self.default_formatter
|
48
|
+
def self.default_formatter(*extra_formatters)
|
49
49
|
::Popro::Formatter::RewriteLine.new(
|
50
50
|
::Popro::Formatter::Concat.new(
|
51
51
|
::Popro::Formatter::Spinner.new(:dots, bounce: true),
|
52
52
|
::Popro::Formatter::Sprintf.new,
|
53
|
+
*extra_formatters,
|
53
54
|
(proc do |_, yielded = nil|
|
54
55
|
yielded if yielded.is_a?(String) || yielded.is_a?(Numeric)
|
55
56
|
end),
|
@@ -58,8 +59,8 @@ module Popro
|
|
58
59
|
)
|
59
60
|
end
|
60
61
|
|
61
|
-
def self.default
|
62
|
-
Stream.new(formatter: default_formatter)
|
62
|
+
def self.default(*extra_formatters)
|
63
|
+
Stream.new(formatter: default_formatter(*extra_formatters))
|
63
64
|
end
|
64
65
|
end
|
65
66
|
end
|
data/lib/popro/info.rb
CHANGED
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
|
46
|
+
%i[each each_will to_proc did will 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.1
|
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: []
|