popro 0.1.2 → 0.2.3

Sign up to get free protection for your applications and to get access to all the features.
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: []