popro 0.1.2 → 0.2.3
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 +4 -0
- data/lib/popro.rb +18 -2
- data/lib/popro/context.rb +30 -9
- data/lib/popro/formatter.rb +48 -1
- data/lib/popro/indicator.rb +36 -4
- data/lib/popro/progress.rb +7 -7
- 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: fc8a91c38e9a66e7b5de492fe92f5def2d044fc118a3dfc25ef826ccadc8692c
|
4
|
+
data.tar.gz: 00fc035091657744a3bc7110b91f1cfb49192d07afce1a0866e20745b038c368
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f0c02a15ce252052573de441631e8665f8c2fde13e27162287a01739df908283514f8fa0eb98056e179c2d6ac139aac89bb4a603abd45ae1d9333d960f2de5e4
|
7
|
+
data.tar.gz: 989554d6b7dcf42c8db7a0a1b240b440acf07fd1b965e861486361fe7627fe4c65d37ae8df951daeae37445d689239397613a34f1e6231d11e5addbccdaf586a
|
data/CHANGELOG
CHANGED
data/lib/popro.rb
CHANGED
@@ -7,7 +7,9 @@ module Popro
|
|
7
7
|
|
8
8
|
require_relative 'popro/progress'
|
9
9
|
|
10
|
-
|
10
|
+
@_is_silenced = false
|
11
|
+
|
12
|
+
def self.new(total = 0, **options, &block)
|
11
13
|
raise ConfigError, 'using :total is not supported in new' if options.key?(:total) && (options[:total] != total)
|
12
14
|
|
13
15
|
options[:total] = total
|
@@ -15,7 +17,6 @@ module Popro
|
|
15
17
|
end
|
16
18
|
|
17
19
|
def self.each(obj, total = nil, **options, &block)
|
18
|
-
options[:step] = 0 unless options.key? :step
|
19
20
|
new(0, **options).each(obj, total, &block).done
|
20
21
|
end
|
21
22
|
|
@@ -23,6 +24,21 @@ module Popro
|
|
23
24
|
new(0, **options).each_will(obj, titler, total, &block).done
|
24
25
|
end
|
25
26
|
|
27
|
+
def self.each_gonna(obj, titler, total = nil, **options, &block)
|
28
|
+
new(0, **options).each_gonna(obj, titler, total, &block).done
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.silenced
|
32
|
+
prev_silenced = @_is_silenced
|
33
|
+
@_is_silenced = true
|
34
|
+
yield
|
35
|
+
@_is_silenced = prev_silenced
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.silenced?
|
39
|
+
@_is_silenced
|
40
|
+
end
|
41
|
+
|
26
42
|
def self.command_line(*_args)
|
27
43
|
raise 'TODO: implement a `ps` style progress indicator for command line'
|
28
44
|
end
|
data/lib/popro/context.rb
CHANGED
@@ -6,11 +6,13 @@ module Popro
|
|
6
6
|
WILL_CHECK_MARKS ||= ' ✔'
|
7
7
|
|
8
8
|
class Context
|
9
|
+
require_relative 'indicator'
|
10
|
+
|
9
11
|
def initialize(progress:, info:, indicator:, step: 1)
|
10
12
|
@progress = progress
|
11
|
-
@indicator = indicator
|
12
13
|
@info = info
|
13
14
|
@step = step
|
15
|
+
@_indicator = indicator
|
14
16
|
end
|
15
17
|
|
16
18
|
def each(obj, total = nil, &block)
|
@@ -39,31 +41,44 @@ module Popro
|
|
39
41
|
raise OutOfSyncError, 'done while not started' unless @info.running?
|
40
42
|
|
41
43
|
@info.finish
|
42
|
-
|
44
|
+
indicator.finish if indicator.respond_to? :finish
|
43
45
|
end
|
44
46
|
|
45
47
|
def formatter(&block)
|
46
|
-
unless @
|
47
|
-
raise ConfigError, "seems formatter is not available for #{@
|
48
|
+
unless @_indicator.respond_to?(:formatter=)
|
49
|
+
raise ConfigError, "seems formatter is not available for #{@_indicator.class}"
|
48
50
|
end
|
49
51
|
|
50
|
-
@
|
52
|
+
@_indicator.formatter = block
|
51
53
|
block
|
52
54
|
end
|
53
55
|
|
54
56
|
def did(yielded = nil, amount = nil)
|
55
57
|
@info.start unless @info.running?
|
56
58
|
amount = @step if amount.nil?
|
57
|
-
raise TypeError
|
59
|
+
raise TypeError, "amount: expected an integer, got #{amount.class}" unless amount.is_a? Integer
|
58
60
|
|
59
61
|
@info.current += amount unless amount.zero?
|
60
|
-
|
62
|
+
indicator.call(@info, yielded)
|
63
|
+
|
64
|
+
self
|
65
|
+
end
|
61
66
|
|
67
|
+
def gonna(title)
|
68
|
+
@info.start unless @info.running?
|
69
|
+
indicator.call(@info, title)
|
62
70
|
self
|
63
71
|
end
|
64
72
|
|
73
|
+
def each_gonna(obj, titler, total = nil, &block)
|
74
|
+
_each(obj, total) do |*args|
|
75
|
+
gonna(titler.call(*args))
|
76
|
+
block.call(*args, progress: @info)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
65
80
|
def will(title = nil, step = nil, &block)
|
66
|
-
|
81
|
+
gonna "#{WILL_CHECK_MARKS[0]} #{title}"
|
67
82
|
|
68
83
|
return self unless block_given?
|
69
84
|
|
@@ -79,9 +94,15 @@ module Popro
|
|
79
94
|
|
80
95
|
private
|
81
96
|
|
97
|
+
def indicator
|
98
|
+
return Indicator::Null if Popro.silenced?
|
99
|
+
|
100
|
+
@_indicator
|
101
|
+
end
|
102
|
+
|
82
103
|
def _each(obj, total = nil, &block)
|
83
104
|
total = obj.size if total.nil?
|
84
|
-
raise TypeError
|
105
|
+
raise TypeError, "total: expected an integer got #{total.class}" unless total.is_a?(Integer) || total.nil?
|
85
106
|
|
86
107
|
@info.total += total if total.positive?
|
87
108
|
# 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
@@ -1,9 +1,25 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'popro'
|
4
|
+
|
3
5
|
module Popro
|
4
6
|
module Indicator
|
5
7
|
require_relative 'formatter'
|
6
8
|
|
9
|
+
class Null
|
10
|
+
def self.new
|
11
|
+
self
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.initialize
|
15
|
+
self
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.call(*_args); end
|
19
|
+
|
20
|
+
def self.finish; end
|
21
|
+
end
|
22
|
+
|
7
23
|
class Aggregate
|
8
24
|
def initialize(*indicators)
|
9
25
|
@indicators = indicators
|
@@ -27,7 +43,7 @@ module Popro
|
|
27
43
|
formatter = self.class.default_formatter(formatter) if formatter.nil? || formatter.is_a?(String)
|
28
44
|
|
29
45
|
@formatter = formatter
|
30
|
-
@stream = stream ||
|
46
|
+
@stream = stream || $stdout
|
31
47
|
end
|
32
48
|
|
33
49
|
def call(*args)
|
@@ -45,11 +61,27 @@ module Popro
|
|
45
61
|
end
|
46
62
|
end
|
47
63
|
|
48
|
-
|
64
|
+
class Callback
|
65
|
+
def initialize(finish = nil, &block)
|
66
|
+
@finish = finish
|
67
|
+
@callback = block
|
68
|
+
end
|
69
|
+
|
70
|
+
def call(*args)
|
71
|
+
@callback.call(*args)
|
72
|
+
end
|
73
|
+
|
74
|
+
def finish
|
75
|
+
@finish&.call
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def self.default_formatter(*extra_formatters)
|
49
80
|
::Popro::Formatter::RewriteLine.new(
|
50
81
|
::Popro::Formatter::Concat.new(
|
51
82
|
::Popro::Formatter::Spinner.new(:dots, bounce: true),
|
52
83
|
::Popro::Formatter::Sprintf.new,
|
84
|
+
*extra_formatters,
|
53
85
|
(proc do |_, yielded = nil|
|
54
86
|
yielded if yielded.is_a?(String) || yielded.is_a?(Numeric)
|
55
87
|
end),
|
@@ -58,8 +90,8 @@ module Popro
|
|
58
90
|
)
|
59
91
|
end
|
60
92
|
|
61
|
-
def self.default
|
62
|
-
Stream.new(formatter: default_formatter)
|
93
|
+
def self.default(*extra_formatters)
|
94
|
+
Stream.new(formatter: default_formatter(*extra_formatters))
|
63
95
|
end
|
64
96
|
end
|
65
97
|
end
|
data/lib/popro/progress.rb
CHANGED
@@ -9,21 +9,21 @@ module Popro
|
|
9
9
|
DEFAULT_OPTIONS ||= {
|
10
10
|
total: 0,
|
11
11
|
current: 0,
|
12
|
+
indicator: Indicator.default
|
12
13
|
}.freeze
|
13
14
|
|
14
15
|
attr_reader :context
|
15
16
|
|
16
17
|
def initialize(**options)
|
17
|
-
options.merge!(DEFAULT_OPTIONS)
|
18
|
-
|
19
18
|
@started = false
|
20
19
|
|
21
|
-
|
20
|
+
options = DEFAULT_OPTIONS
|
21
|
+
.merge(step: block_given? ? 0 : 1)
|
22
|
+
.merge(options)
|
22
23
|
|
23
|
-
|
24
|
-
indicator = Indicator.default unless options.key? :indicator
|
24
|
+
@info = Info.new(total: options.delete(:total), current: options.delete(:current))
|
25
25
|
|
26
|
-
options.merge!(progress: self, info: @info
|
26
|
+
options.merge!(progress: self, info: @info)
|
27
27
|
@context = Context.new(**options)
|
28
28
|
|
29
29
|
register_aliases
|
@@ -43,7 +43,7 @@ module Popro
|
|
43
43
|
|
44
44
|
def register_aliases
|
45
45
|
class << self
|
46
|
-
%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|
|
47
47
|
define_method method_name do |*args, &block|
|
48
48
|
@context.public_send(method_name, *args, &block)
|
49
49
|
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.3
|
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: []
|