popro 0.1.1 → 0.2.2

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: 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: []