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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c0ed84ff76f7db2ab74b649ef29f62dab630f3b12dc0e2a8cf011382814d9396
4
- data.tar.gz: ff292d589ecdfd671fe1136079611bc45ccbec5c262c2b831baef59799732de9
3
+ metadata.gz: fc8a91c38e9a66e7b5de492fe92f5def2d044fc118a3dfc25ef826ccadc8692c
4
+ data.tar.gz: 00fc035091657744a3bc7110b91f1cfb49192d07afce1a0866e20745b038c368
5
5
  SHA512:
6
- metadata.gz: 810c7e4925421c86e3585d429a948f50de6ea913042b9c3edc6d13a63557286e9ca83f2d6c973700388d5934aff9097071b78db7c6b0c3eb162e6fba6666e566
7
- data.tar.gz: ffab387b8fbed5b19e88d58d97a3001cff0f7855b9154754acd114c6bdd53bb846085d47fb04f7ed7c3a3972315f400a71dbbb6e28519a45b30243df39180f4a
6
+ metadata.gz: f0c02a15ce252052573de441631e8665f8c2fde13e27162287a01739df908283514f8fa0eb98056e179c2d6ac139aac89bb4a603abd45ae1d9333d960f2de5e4
7
+ data.tar.gz: 989554d6b7dcf42c8db7a0a1b240b440acf07fd1b965e861486361fe7627fe4c65d37ae8df951daeae37445d689239397613a34f1e6231d11e5addbccdaf586a
data/CHANGELOG CHANGED
@@ -1 +1,5 @@
1
+ 0.2.3 add support for `Popro.silenced`
2
+ 0.2.2 add gonna and each_gonna, add Callback Indicator
3
+ 0.2.1 add support for estimation and re-use of default indicator with added concatted formatters
4
+ 0.2.0 various fixes and added unit tests
1
5
  0.0.1 initial version
@@ -7,7 +7,9 @@ module Popro
7
7
 
8
8
  require_relative 'popro/progress'
9
9
 
10
- def self.new(total, **options, &block)
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
@@ -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
- @indicator.finish if @indicator.respond_to? :finish
44
+ indicator.finish if indicator.respond_to? :finish
43
45
  end
44
46
 
45
47
  def formatter(&block)
46
- unless @indicator.respond_to?(:formatter=)
47
- raise ConfigError, "seems formatter is not available for #{@indicator.class}"
48
+ unless @_indicator.respond_to?(:formatter=)
49
+ raise ConfigError, "seems formatter is not available for #{@_indicator.class}"
48
50
  end
49
51
 
50
- @indicator.formatter = block
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('amount: expected an integer') unless amount.is_a? Integer
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
- @indicator.call(@info, yielded)
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
- did "#{WILL_CHECK_MARKS[0]} #{title}", 0
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('total: expected an integer') unless total.is_a?(Integer) || total.nil?
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?
@@ -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" + result.ljust(@longest, ' ')
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
@@ -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 || STDOUT
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
- def self.default_formatter
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
@@ -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
- @info = Info.new(total: options.delete(:total), current: options.delete(:current))
20
+ options = DEFAULT_OPTIONS
21
+ .merge(step: block_given? ? 0 : 1)
22
+ .merge(options)
22
23
 
23
- options[:step] ||= (block_given? ? 0 : 1)
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, indicator: indicator)
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 did will formatter start done].each do |method_name|
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.1.2
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-06-01 00:00:00.000000000 Z
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: '0'
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: []