planter-cli 3.0.1 → 3.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (104) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.gitmodules +3 -0
  4. data/CHANGELOG.md +10 -0
  5. data/README.md +5 -3
  6. data/bin/plant +1 -1
  7. data/docker/Dockerfile +2 -4
  8. data/docker/Dockerfile-2.6 +3 -5
  9. data/docker/Dockerfile-2.7 +2 -4
  10. data/docker/Dockerfile-3.0 +2 -3
  11. data/docker/Dockerfile-3.3 +11 -0
  12. data/docker/sources.list +11 -0
  13. data/lib/planter/filelist.rb +5 -4
  14. data/lib/planter/plant.rb +3 -3
  15. data/lib/planter/prompt.rb +5 -5
  16. data/lib/planter/string.rb +22 -0
  17. data/lib/planter/tag.rb +39 -2
  18. data/lib/planter/version.rb +1 -1
  19. data/lib/planter.rb +30 -17
  20. data/lib/tty-spinner/.editorconfig +9 -0
  21. data/lib/tty-spinner/.github/FUNDING.yml +1 -0
  22. data/lib/tty-spinner/.github/ISSUE_TEMPLATE/BUG_REPORT.md +31 -0
  23. data/lib/tty-spinner/.github/ISSUE_TEMPLATE/FEATURE_REQUEST.md +23 -0
  24. data/lib/tty-spinner/.github/ISSUE_TEMPLATE/config.yml +5 -0
  25. data/lib/tty-spinner/.github/PULL_REQUEST_TEMPLATE.md +19 -0
  26. data/lib/tty-spinner/.github/workflows/ci.yml +59 -0
  27. data/lib/tty-spinner/.gitignore +14 -0
  28. data/lib/tty-spinner/.rspec +2 -0
  29. data/lib/tty-spinner/.rubocop.yml +78 -0
  30. data/lib/tty-spinner/CHANGELOG.md +151 -0
  31. data/lib/tty-spinner/CODE_OF_CONDUCT.md +132 -0
  32. data/lib/tty-spinner/Gemfile +17 -0
  33. data/lib/tty-spinner/LICENSE.txt +22 -0
  34. data/lib/tty-spinner/README.md +581 -0
  35. data/lib/tty-spinner/Rakefile +10 -0
  36. data/lib/tty-spinner/appveyor.yml +33 -0
  37. data/lib/tty-spinner/bin/console +14 -0
  38. data/lib/tty-spinner/bin/setup +8 -0
  39. data/lib/tty-spinner/demo.gif +0 -0
  40. data/lib/tty-spinner/examples/auto_spin.rb +10 -0
  41. data/lib/tty-spinner/examples/basic.rb +10 -0
  42. data/lib/tty-spinner/examples/clear.rb +11 -0
  43. data/lib/tty-spinner/examples/color.rb +14 -0
  44. data/lib/tty-spinner/examples/error.rb +11 -0
  45. data/lib/tty-spinner/examples/formats.rb +13 -0
  46. data/lib/tty-spinner/examples/hide_cursor.rb +14 -0
  47. data/lib/tty-spinner/examples/log.rb +13 -0
  48. data/lib/tty-spinner/examples/multi/basic.rb +15 -0
  49. data/lib/tty-spinner/examples/multi/basic_top_level.rb +15 -0
  50. data/lib/tty-spinner/examples/multi/custom_style.rb +28 -0
  51. data/lib/tty-spinner/examples/multi/files.rb +16 -0
  52. data/lib/tty-spinner/examples/multi/jobs.rb +11 -0
  53. data/lib/tty-spinner/examples/multi/multi.rb +19 -0
  54. data/lib/tty-spinner/examples/multi/multi_top_level.rb +20 -0
  55. data/lib/tty-spinner/examples/multi/pause.rb +28 -0
  56. data/lib/tty-spinner/examples/multi/threaded.rb +30 -0
  57. data/lib/tty-spinner/examples/pause.rb +24 -0
  58. data/lib/tty-spinner/examples/run.rb +20 -0
  59. data/lib/tty-spinner/examples/success.rb +11 -0
  60. data/lib/tty-spinner/examples/threaded.rb +13 -0
  61. data/lib/tty-spinner/examples/update.rb +13 -0
  62. data/lib/tty-spinner/lib/tty/spinner/formats.rb +274 -0
  63. data/lib/tty-spinner/lib/tty/spinner/multi.rb +352 -0
  64. data/lib/tty-spinner/lib/tty/spinner/version.rb +7 -0
  65. data/lib/tty-spinner/lib/tty/spinner.rb +604 -0
  66. data/lib/tty-spinner/lib/tty-spinner.rb +2 -0
  67. data/lib/tty-spinner/spec/spec_helper.rb +52 -0
  68. data/lib/tty-spinner/spec/unit/auto_spin_spec.rb +25 -0
  69. data/lib/tty-spinner/spec/unit/clear_spec.rb +16 -0
  70. data/lib/tty-spinner/spec/unit/error_spec.rb +53 -0
  71. data/lib/tty-spinner/spec/unit/events_spec.rb +35 -0
  72. data/lib/tty-spinner/spec/unit/formats_spec.rb +9 -0
  73. data/lib/tty-spinner/spec/unit/frames_spec.rb +31 -0
  74. data/lib/tty-spinner/spec/unit/hide_cursor_spec.rb +51 -0
  75. data/lib/tty-spinner/spec/unit/job_spec.rb +12 -0
  76. data/lib/tty-spinner/spec/unit/join_spec.rb +10 -0
  77. data/lib/tty-spinner/spec/unit/log_spec.rb +60 -0
  78. data/lib/tty-spinner/spec/unit/multi/auto_spin_spec.rb +32 -0
  79. data/lib/tty-spinner/spec/unit/multi/error_spec.rb +107 -0
  80. data/lib/tty-spinner/spec/unit/multi/line_inset_spec.rb +57 -0
  81. data/lib/tty-spinner/spec/unit/multi/on_spec.rb +11 -0
  82. data/lib/tty-spinner/spec/unit/multi/register_spec.rb +46 -0
  83. data/lib/tty-spinner/spec/unit/multi/spin_spec.rb +101 -0
  84. data/lib/tty-spinner/spec/unit/multi/stop_spec.rb +95 -0
  85. data/lib/tty-spinner/spec/unit/multi/success_spec.rb +108 -0
  86. data/lib/tty-spinner/spec/unit/new_spec.rb +25 -0
  87. data/lib/tty-spinner/spec/unit/pause_spec.rb +43 -0
  88. data/lib/tty-spinner/spec/unit/reset_spec.rb +19 -0
  89. data/lib/tty-spinner/spec/unit/run_spec.rb +30 -0
  90. data/lib/tty-spinner/spec/unit/spin_spec.rb +117 -0
  91. data/lib/tty-spinner/spec/unit/stop_spec.rb +88 -0
  92. data/lib/tty-spinner/spec/unit/success_spec.rb +53 -0
  93. data/lib/tty-spinner/spec/unit/tty_spec.rb +8 -0
  94. data/lib/tty-spinner/spec/unit/update_spec.rb +85 -0
  95. data/lib/tty-spinner/tasks/console.rake +11 -0
  96. data/lib/tty-spinner/tasks/coverage.rake +11 -0
  97. data/lib/tty-spinner/tasks/spec.rake +29 -0
  98. data/lib/tty-spinner/tty-spinner.gemspec +36 -0
  99. data/scripts/runtests.sh +1 -1
  100. data/spec/cli_spec.rb +27 -0
  101. data/spec/spec_helper.rb +26 -0
  102. data/spec/templates/test/_planter.yml +3 -6
  103. data/src/_README.md +5 -3
  104. metadata +86 -2
@@ -0,0 +1,352 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "monitor"
4
+ require "forwardable"
5
+
6
+ require_relative "../spinner"
7
+
8
+ module TTY
9
+ class Spinner
10
+ # Used for managing multiple terminal spinners
11
+ #
12
+ # @api public
13
+ class Multi
14
+ include Enumerable
15
+ include MonitorMixin
16
+
17
+ extend Forwardable
18
+
19
+ def_delegators :@spinners, :each, :empty?, :length
20
+
21
+ DEFAULT_INSET = {
22
+ top: Gem.win_platform? ? "+ " : "\u250c ",
23
+ middle: Gem.win_platform? ? "|-- " : "\u251c\u2500\u2500 ",
24
+ bottom: Gem.win_platform? ? "|__ " : "\u2514\u2500\u2500 "
25
+ }.freeze
26
+
27
+ # The current count of all rendered rows
28
+ #
29
+ # @api public
30
+ attr_reader :rows
31
+
32
+ # Initialize a multispinner
33
+ #
34
+ # @example
35
+ # spinner = TTY::Spinner::Multi.new
36
+ #
37
+ # @param [String] message
38
+ # the optional message to print in front of the top level spinner
39
+ #
40
+ # @param [Hash] options
41
+ # @option options [Hash] :style
42
+ # keys :top :middle and :bottom can contain Strings that are used to
43
+ # indent the spinners. Ignored if message is blank
44
+ # @option options [Object] :output
45
+ # the object that responds to print call defaulting to stderr
46
+ # @option options [Boolean] :hide_cursor
47
+ # display or hide cursor
48
+ # @option options [Boolean] :clear
49
+ # clear ouptut when finished
50
+ # @option options [Float] :interval
51
+ # the interval for auto spinning
52
+ #
53
+ # @api public
54
+ def initialize(*args)
55
+ super()
56
+ @options = args.last.is_a?(::Hash) ? args.pop : {}
57
+ message = args.empty? ? nil : args.pop
58
+ @inset_opts = @options.delete(:style) { DEFAULT_INSET }
59
+ @rows = 0
60
+ @spinners = []
61
+ @spinners_count = 0
62
+ @top_spinner = nil
63
+ @last_spin_at = nil
64
+ unless message.nil?
65
+ @top_spinner = register(message, observable: false, row: next_row)
66
+ end
67
+
68
+ @callbacks = {
69
+ success: [],
70
+ error: [],
71
+ done: [],
72
+ spin: []
73
+ }
74
+ end
75
+
76
+ # Register a new spinner
77
+ #
78
+ # @param [String, TTY::Spinner] pattern_or_spinner
79
+ # the pattern used for creating spinner, or a spinner instance
80
+ #
81
+ # @api public
82
+ def register(pattern_or_spinner, **options, &job)
83
+ observable = options.delete(:observable) { true }
84
+ spinner = nil
85
+
86
+ synchronize do
87
+ spinner = create_spinner(pattern_or_spinner, options)
88
+ spinner.attach_to(self)
89
+ spinner.job(&job) if block_given?
90
+ observe(spinner) if observable
91
+ @spinners << spinner
92
+ @spinners_count += 1
93
+ if @top_spinner
94
+ @spinners.each { |sp| sp.redraw_indent if sp.spinning? || sp.done? }
95
+ end
96
+ end
97
+
98
+ spinner
99
+ end
100
+
101
+ # Create a spinner instance
102
+ #
103
+ # @api private
104
+ def create_spinner(pattern_or_spinner, options)
105
+ case pattern_or_spinner
106
+ when ::String
107
+ TTY::Spinner.new(
108
+ pattern_or_spinner,
109
+ @options.merge(options)
110
+ )
111
+ when ::TTY::Spinner
112
+ pattern_or_spinner
113
+ else
114
+ raise ArgumentError, "Expected a pattern or spinner, " \
115
+ "got: #{pattern_or_spinner.class}"
116
+ end
117
+ end
118
+
119
+ # Increase a row count
120
+ #
121
+ # @api public
122
+ def next_row
123
+ synchronize do
124
+ @rows += 1
125
+ end
126
+ end
127
+
128
+ # Get the top level spinner if it exists
129
+ #
130
+ # @return [TTY::Spinner] the top level spinner
131
+ #
132
+ # @api public
133
+ def top_spinner
134
+ raise "No top level spinner" if @top_spinner.nil?
135
+
136
+ @top_spinner
137
+ end
138
+
139
+ # Auto spin the top level spinner & all child spinners
140
+ # that have scheduled jobs
141
+ #
142
+ # @api public
143
+ def auto_spin
144
+ raise "No top level spinner" if @top_spinner.nil?
145
+
146
+ jobs = []
147
+ @spinners.each do |spinner|
148
+ if spinner.job?
149
+ spinner.auto_spin
150
+ jobs << Thread.new { spinner.execute_job }
151
+ end
152
+ end
153
+ jobs.each(&:join)
154
+ end
155
+
156
+ # Perform a single spin animation
157
+ #
158
+ # @api public
159
+ def spin
160
+ raise "No top level spinner" if @top_spinner.nil?
161
+
162
+ synchronize do
163
+ throttle { @top_spinner.spin }
164
+ end
165
+ end
166
+
167
+ # Pause all spinners
168
+ #
169
+ # @api public
170
+ def pause
171
+ @spinners.dup.each(&:pause)
172
+ end
173
+
174
+ # Resume all spinners
175
+ #
176
+ # @api public
177
+ def resume
178
+ @spinners.dup.each(&:resume)
179
+ end
180
+
181
+ # Find the number of characters to move into the line
182
+ # before printing the spinner
183
+ #
184
+ # @param [Integer] line_no
185
+ # the current spinner line number for which line inset is calculated
186
+ #
187
+ # @return [String]
188
+ # the inset
189
+ #
190
+ # @api public
191
+ def line_inset(line_no)
192
+ return "" if @top_spinner.nil?
193
+
194
+ if line_no == 1
195
+ @inset_opts[:top]
196
+ elsif line_no == @spinners_count
197
+ @inset_opts[:bottom]
198
+ else
199
+ @inset_opts[:middle]
200
+ end
201
+ end
202
+
203
+ # Check if all spinners are done
204
+ #
205
+ # @return [Boolean]
206
+ #
207
+ # @api public
208
+ def done?
209
+ synchronize do
210
+ (@spinners - [@top_spinner]).all?(&:done?)
211
+ end
212
+ end
213
+
214
+ # Check if all spinners succeeded
215
+ #
216
+ # @return [Boolean]
217
+ #
218
+ # @api public
219
+ def success?
220
+ synchronize do
221
+ (@spinners - [@top_spinner]).all?(&:success?)
222
+ end
223
+ end
224
+
225
+ # Check if any spinner errored
226
+ #
227
+ # @return [Boolean]
228
+ #
229
+ # @api public
230
+ def error?
231
+ synchronize do
232
+ (@spinners - [@top_spinner]).any?(&:error?)
233
+ end
234
+ end
235
+
236
+ # Stop all spinners
237
+ #
238
+ # @api public
239
+ def stop
240
+ @spinners.dup.each(&:stop)
241
+ end
242
+
243
+ # Stop all spinners with success status
244
+ #
245
+ # @api public
246
+ def success
247
+ @spinners.dup.each(&:success)
248
+ end
249
+
250
+ # Stop all spinners with error status
251
+ #
252
+ # @api public
253
+ def error
254
+ @spinners.dup.each(&:error)
255
+ end
256
+
257
+ # Listen on event
258
+ #
259
+ # @api public
260
+ def on(key, &callback)
261
+ unless @callbacks.key?(key)
262
+ raise ArgumentError, "The event #{key} does not exist. " \
263
+ " Use :spin, :success, :error, or :done instead"
264
+ end
265
+ @callbacks[key] << callback
266
+ self
267
+ end
268
+
269
+ private
270
+
271
+ # Check if this spinner should revolve to keep constant speed
272
+ # matching top spinner interval
273
+ #
274
+ # @api private
275
+ def throttle
276
+ sleep_time = 1.0 / @top_spinner.interval
277
+ return if @last_spin_at && Time.now - @last_spin_at < sleep_time
278
+
279
+ yield if block_given?
280
+ @last_spin_at = Time.now
281
+ end
282
+
283
+ # Fire an event
284
+ #
285
+ # @api private
286
+ def emit(key, *args)
287
+ @callbacks[key].each do |block|
288
+ block.call(*args)
289
+ end
290
+ end
291
+
292
+ # Observe spinner for events to notify top spinner of current state
293
+ #
294
+ # @param [TTY::Spinner] spinner
295
+ # the spinner to listen to for events
296
+ #
297
+ # @api private
298
+ def observe(spinner)
299
+ spinner.on(:spin, &spin_handler)
300
+ .on(:success, &success_handler)
301
+ .on(:error, &error_handler)
302
+ .on(:done, &done_handler)
303
+ end
304
+
305
+ # Handle spin event
306
+ #
307
+ # @api private
308
+ def spin_handler
309
+ proc do
310
+ spin if @top_spinner
311
+ emit(:spin)
312
+ end
313
+ end
314
+
315
+ # Handle the success state
316
+ #
317
+ # @api private
318
+ def success_handler
319
+ proc do
320
+ if success?
321
+ @top_spinner.success if @top_spinner
322
+ emit(:success)
323
+ end
324
+ end
325
+ end
326
+
327
+ # Handle the error state
328
+ #
329
+ # @api private
330
+ def error_handler
331
+ proc do
332
+ if error?
333
+ @top_spinner.error if @top_spinner
334
+ @fired ||= emit(:error) # fire once
335
+ end
336
+ end
337
+ end
338
+
339
+ # Handle the done state
340
+ #
341
+ # @api private
342
+ def done_handler
343
+ proc do
344
+ if done?
345
+ @top_spinner.stop if @top_spinner && !error? && !success?
346
+ emit(:done)
347
+ end
348
+ end
349
+ end
350
+ end # MultiSpinner
351
+ end # Spinner
352
+ end # TTY
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TTY
4
+ class Spinner
5
+ VERSION = "0.9.3"
6
+ end # Spinner
7
+ end # TTY