popro 0.1.1 → 0.2.2

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: ce1a842c500f314f3ed8ba0e7e9deb5a4ece7cbf81ea11563664336cf35ddcd1
4
- data.tar.gz: 3d313f96ff1b5dda33e51ec994ee592447e957201ebf059b86caef3d0d830c53
3
+ metadata.gz: a790befdf497a693172bb0faf40561c1d7fd6e287a3b5c379f7ddd9496f33509
4
+ data.tar.gz: a015de37abef0c5769a5d786182319fb891e874124daa5503a7feb9b411438fe
5
5
  SHA512:
6
- metadata.gz: d68080c7a53d74a50e15fdb252f7aacbc57616a9de4aeb12bff133f715c347f07cdb6c9e2643d769a48babf01c6eb127e9e2dd6bdcd3d028d460efda34068d3b
7
- data.tar.gz: f699ce90d06692c3ccfa71a342e1eceda39456c0599891c535f024ff0b64cec5eb8c8a56d5d91f83d96f300d5009c8098a7f73cdcb62ccf778fbc0a7feb0b96b
6
+ metadata.gz: 0a2b3c066fe0a666537e40a2d63b81442e463c4b421a29d67722ad364453695fe17ea247a66c8d2e695e389b1482b56788dc03efff8836821a63f61d0592a5dd
7
+ data.tar.gz: 87151aae4f7c3ac0650960e5fdf646d4a373742dec759e3872fb8ea3be96c5b64b585401e6b6897c57ed7c86ed23987f1d33f426ffafbabf8e50558348046d3f
data/CHANGELOG CHANGED
@@ -1 +1,4 @@
1
+ 0.2.2 add gonna and each_gonna, add Callback Indicator
2
+ 0.2.1 add support for estimation and re-use of default indicator with added concatted formatters
3
+ 0.2.0 various fixes and added unit tests
1
4
  0.0.1 initial version
data/README.md CHANGED
@@ -1,13 +1,20 @@
1
1
  # Po'Pro: The Poor-Man's Progress Indicator
2
2
 
3
+ [![Version](https://badge.fury.io/rb/popro.svg)](https://badge.fury.io/rb/popro)
4
+ [![Tests](https://github.com/MikeSmithEU/PoPro/workflows/Code%20quality%20&%20unit%20tests/badge.svg)](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 `PoproFormatter::*` classes).
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 `PoproInfo` containing e.g. `current` and `total`.
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 `PoproIndicator` module).
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 `PoproIndicator` class is `PoproIndicator.default` (which returns an instance of `PoproIndicator::Stream`), which outputs the progress to STDOUT each time `Popro#did` or `Popro#will` is called.
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
 
@@ -7,7 +7,7 @@ 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
@@ -15,7 +15,6 @@ module Popro
15
15
  end
16
16
 
17
17
  def self.each(obj, total = nil, **options, &block)
18
- options[:step] = 0 unless options.key? :step
19
18
  new(0, **options).each(obj, total, &block).done
20
19
  end
21
20
 
@@ -23,6 +22,10 @@ module Popro
23
22
  new(0, **options).each_will(obj, titler, total, &block).done
24
23
  end
25
24
 
25
+ def self.each_gonna(obj, titler, total = nil, **options, &block)
26
+ new(0, **options).each_gonna(obj, titler, total, &block).done
27
+ end
28
+
26
29
  def self.command_line(*_args)
27
30
  raise 'TODO: implement a `ps` style progress indicator for command line'
28
31
  end
@@ -54,7 +54,7 @@ module Popro
54
54
  def did(yielded = nil, amount = nil)
55
55
  @info.start unless @info.running?
56
56
  amount = @step if amount.nil?
57
- raise TypeError('amount: expected an integer') unless amount.is_a? Integer
57
+ raise TypeError, "amount: expected an integer, got #{amount.class}" unless amount.is_a? Integer
58
58
 
59
59
  @info.current += amount unless amount.zero?
60
60
  @indicator.call(@info, yielded)
@@ -62,8 +62,20 @@ module Popro
62
62
  self
63
63
  end
64
64
 
65
+ def gonna(title)
66
+ @indicator.call(@info, title)
67
+ self
68
+ end
69
+
70
+ def each_gonna(obj, titler, total = nil, &block)
71
+ _each(obj, total) do |*args|
72
+ gonna(titler.call(*args))
73
+ block.call(*args, progress: @info) if block_given?
74
+ end
75
+ end
76
+
65
77
  def will(title = nil, step = nil, &block)
66
- did "#{WILL_CHECK_MARKS[0]} #{title}", 0
78
+ gonna "#{WILL_CHECK_MARKS[0]} #{title}"
67
79
 
68
80
  return self unless block_given?
69
81
 
@@ -81,7 +93,7 @@ module Popro
81
93
 
82
94
  def _each(obj, total = nil, &block)
83
95
  total = obj.size if total.nil?
84
- raise TypeError('total: expected an integer') unless total.is_a?(Integer) || total.nil?
96
+ raise TypeError, "total: expected an integer got #{total.class}" unless total.is_a?(Integer) || total.nil?
85
97
 
86
98
  @info.total += total if total.positive?
87
99
  # 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
@@ -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 || STDOUT
30
+ @stream = stream || $stdout
31
31
  end
32
32
 
33
33
  def call(*args)
@@ -45,11 +45,27 @@ module Popro
45
45
  end
46
46
  end
47
47
 
48
- def self.default_formatter
48
+ class Callback
49
+ def initialize(finish = nil, &block)
50
+ @finish = finish
51
+ @callback = block
52
+ end
53
+
54
+ def call(*args)
55
+ @callback.call(*args)
56
+ end
57
+
58
+ def finish
59
+ @finish&.call
60
+ end
61
+ end
62
+
63
+ def self.default_formatter(*extra_formatters)
49
64
  ::Popro::Formatter::RewriteLine.new(
50
65
  ::Popro::Formatter::Concat.new(
51
66
  ::Popro::Formatter::Spinner.new(:dots, bounce: true),
52
67
  ::Popro::Formatter::Sprintf.new,
68
+ *extra_formatters,
53
69
  (proc do |_, yielded = nil|
54
70
  yielded if yielded.is_a?(String) || yielded.is_a?(Numeric)
55
71
  end),
@@ -58,8 +74,8 @@ module Popro
58
74
  )
59
75
  end
60
76
 
61
- def self.default
62
- Stream.new(formatter: default_formatter)
77
+ def self.default(*extra_formatters)
78
+ Stream.new(formatter: default_formatter(*extra_formatters))
63
79
  end
64
80
  end
65
81
  end
@@ -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[:step] ||= (block_given? ? 0 : 1)
16
- options[:progress] = self
17
- options[:info] = @info
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 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|
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.1.1
4
+ version: 0.2.2
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: []