popro 0.1.3 → 0.2.4
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 +5 -0
- data/lib/popro.rb +28 -2
- data/lib/popro/context.rb +30 -9
- data/lib/popro/formatter.rb +72 -1
- data/lib/popro/indicator.rb +36 -4
- data/lib/popro/progress.rb +6 -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: 8c3d8c8dba5a532d23b95582322983b844243a72679bff15acce69933c106ea2
|
4
|
+
data.tar.gz: ea5170d62aa990167c89d0fee9d7ee07d1cb1902f0a8e64f1920abbb523ed446
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9023ad0fbf774e02fab5dc99df4720365a742c651469342bed04326fa88a34dd7e91d04830f50a4d28ac28a677e660a93715b6b51688b17668933cf0bdc3276e
|
7
|
+
data.tar.gz: b79e9a485d34aaab14bd7674a3adfad80305ba9c87b0ff8a7cd1981ec5dd6afeaef263efab503cef06065662c5d1ad296e7bec3c49c56e21117028fb691a5d7e
|
data/CHANGELOG
CHANGED
@@ -1 +1,6 @@
|
|
1
|
+
0.2.4 add support for `Popro.(un)silence!` atomic silencing, better duration formatting
|
2
|
+
0.2.3 add support for `Popro.silenced`
|
3
|
+
0.2.2 add gonna and each_gonna, add Callback Indicator
|
4
|
+
0.2.1 add support for estimation and re-use of default indicator with added concatted formatters
|
5
|
+
0.2.0 various fixes and added unit tests
|
1
6
|
0.0.1 initial version
|
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,31 @@ 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.silence!
|
39
|
+
@_is_silenced = true
|
40
|
+
self
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.unsilence!
|
44
|
+
@_is_silenced = false
|
45
|
+
self
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.silenced?
|
49
|
+
@_is_silenced
|
50
|
+
end
|
51
|
+
|
26
52
|
def self.command_line(*_args)
|
27
53
|
raise 'TODO: implement a `ps` style progress indicator for command line'
|
28
54
|
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,77 @@ 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
|
+
UNITS = [
|
67
|
+
[60, '%02ds'],
|
68
|
+
[60, '%02dm'],
|
69
|
+
[24, '%02dh'],
|
70
|
+
[7, '%d days, '],
|
71
|
+
[52, '%d weeks, '],
|
72
|
+
[nil, '%d years, ']
|
73
|
+
].freeze
|
74
|
+
|
75
|
+
def elapsed
|
76
|
+
current_time - @start_time
|
77
|
+
end
|
78
|
+
|
79
|
+
def estimated_total
|
80
|
+
return nil if info.current.zero? || info.total.zero?
|
81
|
+
|
82
|
+
elapsed + (info.total / info.current) * elapsed
|
83
|
+
end
|
84
|
+
|
85
|
+
def estimated_left
|
86
|
+
return nil if info.current.zero? || info.total.zero?
|
87
|
+
|
88
|
+
(info.total / info.current) * elapsed
|
89
|
+
end
|
90
|
+
|
91
|
+
def format_duration(secs)
|
92
|
+
return '?' if secs.nil?
|
93
|
+
|
94
|
+
return format('%.3fs', secs) if secs < 10
|
95
|
+
|
96
|
+
format_duration_long(secs)
|
97
|
+
end
|
98
|
+
|
99
|
+
def format_duration_long(secs)
|
100
|
+
UNITS.map do |(divisor, format_str)|
|
101
|
+
next if secs < 1
|
102
|
+
|
103
|
+
if divisor
|
104
|
+
amount = secs % divisor
|
105
|
+
secs /= divisor
|
106
|
+
end
|
107
|
+
|
108
|
+
format(format_str, divisor ? amount : secs)
|
109
|
+
end.take_while(&:itself).reverse!.join
|
110
|
+
end
|
111
|
+
|
112
|
+
def current_time
|
113
|
+
Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
46
117
|
class Sprintf
|
47
118
|
def initialize(format_string = nil)
|
48
119
|
@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,20 +9,19 @@ 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
|
-
|
22
|
-
|
23
|
-
|
20
|
+
options = DEFAULT_OPTIONS
|
21
|
+
.merge(step: block_given? ? 0 : 1)
|
22
|
+
.merge(options)
|
24
23
|
|
25
|
-
|
24
|
+
@info = Info.new(total: options.delete(:total), current: options.delete(:current))
|
26
25
|
|
27
26
|
options.merge!(progress: self, info: @info)
|
28
27
|
@context = Context.new(**options)
|
@@ -44,7 +43,7 @@ module Popro
|
|
44
43
|
|
45
44
|
def register_aliases
|
46
45
|
class << self
|
47
|
-
%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|
|
48
47
|
define_method method_name do |*args, &block|
|
49
48
|
@context.public_send(method_name, *args, &block)
|
50
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.4
|
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-20 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: []
|