is-term 0.8.0
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 +7 -0
- data/LICENSE +674 -0
- data/README.md +2 -0
- data/lib/is-term/boolean.rb +36 -0
- data/lib/is-term/formats.rb +102 -0
- data/lib/is-term/functions.rb +476 -0
- data/lib/is-term/info.rb +23 -0
- data/lib/is-term/statustable.rb +410 -0
- data/lib/is-term/string_helpers.rb +198 -0
- data/lib/is-term.rb +0 -0
- metadata +130 -0
data/README.md
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Boolean
|
|
4
|
+
|
|
5
|
+
include Comparable
|
|
6
|
+
|
|
7
|
+
# +false+ ⇒ +0+
|
|
8
|
+
# +true+ ⇒ +1+
|
|
9
|
+
# @return [Integer]
|
|
10
|
+
def to_i
|
|
11
|
+
if self
|
|
12
|
+
1
|
|
13
|
+
else
|
|
14
|
+
0
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# +false < true+
|
|
19
|
+
# @return [Integer]
|
|
20
|
+
def <=> other
|
|
21
|
+
if other.is_a?(Boolean)
|
|
22
|
+
self.to_i <=> other.to_i
|
|
23
|
+
else
|
|
24
|
+
nil
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
class TrueClass
|
|
31
|
+
include Boolean
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
class FalseClass
|
|
35
|
+
include Boolean
|
|
36
|
+
end
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'info'
|
|
4
|
+
require_relative 'string_helpers'
|
|
5
|
+
require_relative 'statustable'
|
|
6
|
+
|
|
7
|
+
module IS::Term::StatusTable::Formats
|
|
8
|
+
|
|
9
|
+
class << self
|
|
10
|
+
|
|
11
|
+
using IS::Term::StringHelpers
|
|
12
|
+
|
|
13
|
+
# @group Formatters
|
|
14
|
+
|
|
15
|
+
# @return [String]
|
|
16
|
+
def duration value
|
|
17
|
+
return '' if value.nil? || value == 0
|
|
18
|
+
value = value.to_i
|
|
19
|
+
result = ''
|
|
20
|
+
m, s = value.divmod 60
|
|
21
|
+
if m == 0
|
|
22
|
+
result = ("%ds" % s)
|
|
23
|
+
else
|
|
24
|
+
result = ("%02ds" % s)
|
|
25
|
+
h, m = m.divmod 60
|
|
26
|
+
if h == 0
|
|
27
|
+
result = ("%dm" % m) + result
|
|
28
|
+
else
|
|
29
|
+
result = ("%02dm" % m) + result
|
|
30
|
+
d, h = h.divmod 24
|
|
31
|
+
if d == 0
|
|
32
|
+
result = ("%dh" % h) + result
|
|
33
|
+
else
|
|
34
|
+
result = ("%dd" % d) + ("%02dh" % h) + result
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
result
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# @return [String]
|
|
42
|
+
def percent_bar value, width, complete: '=', incomplete: ' ', head: '>', done: '≡'
|
|
43
|
+
return '' if value.nil?
|
|
44
|
+
if value >= 100
|
|
45
|
+
done * (width / done.width)
|
|
46
|
+
elsif value == 0
|
|
47
|
+
incomplete * (width / incomplete.width)
|
|
48
|
+
else
|
|
49
|
+
point = 100 / width
|
|
50
|
+
i = (100 - value) / (point * incomplete.width)
|
|
51
|
+
#h = 1
|
|
52
|
+
c = width - i * incomplete.width - head.width
|
|
53
|
+
if c < 0
|
|
54
|
+
i += c
|
|
55
|
+
c = 0
|
|
56
|
+
end
|
|
57
|
+
complete * c + head + incomplete * i
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# @endgroup
|
|
62
|
+
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
SPECIAL_FORMATS = [ :duration ]
|
|
66
|
+
|
|
67
|
+
class << self
|
|
68
|
+
|
|
69
|
+
# @group Formatter Access
|
|
70
|
+
|
|
71
|
+
# @return [Proc]
|
|
72
|
+
def fmt desc
|
|
73
|
+
case desc
|
|
74
|
+
when String
|
|
75
|
+
lambda do |value|
|
|
76
|
+
return '' if value.nil?
|
|
77
|
+
desc % value
|
|
78
|
+
end
|
|
79
|
+
when Symbol
|
|
80
|
+
raise NameError, "Invalid format name: #{ desc.inspect }", caller_locations unless SPECIAL_FORMATS.include?(desc)
|
|
81
|
+
self.method(desc).to_proc
|
|
82
|
+
else
|
|
83
|
+
raise ArgumentError, "Invalid format: #{ desc.inspect }", caller_locations
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# @return [Proc]
|
|
88
|
+
def bar width, complete: '=', incomplete: ' ', head: '>', done: '≡'
|
|
89
|
+
opts = {
|
|
90
|
+
complete: complete,
|
|
91
|
+
incomplete: incomplete,
|
|
92
|
+
head: head,
|
|
93
|
+
done: done
|
|
94
|
+
}
|
|
95
|
+
lambda { |value| self.percent_bar(value, width, **opts) }
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# @endgroup
|
|
99
|
+
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
end
|
|
@@ -0,0 +1,476 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'info'
|
|
4
|
+
require_relative 'statustable'
|
|
5
|
+
|
|
6
|
+
# Provides calculation functions for status table rows and aggregates.
|
|
7
|
+
#
|
|
8
|
+
# This module contains methods for retrieving and calculating timing metrics
|
|
9
|
+
# (start/finish times, elapsed time, estimated completion), progress percentages,
|
|
10
|
+
# and aggregate statistics (sum, average, min, max, count) for rows in a
|
|
11
|
+
# {IS::Term::StatusTable}.
|
|
12
|
+
#
|
|
13
|
+
# Methods support polymorphic signatures accepting either a Hash row,
|
|
14
|
+
# an identifier, or no argument (for table-wide aggregation).
|
|
15
|
+
#
|
|
16
|
+
# @example Calculating progress for a specific row
|
|
17
|
+
# percent(some_row) # => 45
|
|
18
|
+
# elapsed(some_row) # => 123.45
|
|
19
|
+
#
|
|
20
|
+
# @example Table-wide aggregation
|
|
21
|
+
# percent # => 32 (percent for entire table)
|
|
22
|
+
# active # => 3 (count of active rows)
|
|
23
|
+
# sum(:size) # => 1024 (sum of :size field across all rows)
|
|
24
|
+
#
|
|
25
|
+
module IS::Term::StatusTable::Functions
|
|
26
|
+
|
|
27
|
+
protected
|
|
28
|
+
|
|
29
|
+
# @group Internal Setup
|
|
30
|
+
|
|
31
|
+
# @api private
|
|
32
|
+
# The status table context for function execution.
|
|
33
|
+
#
|
|
34
|
+
# Returns the singleton instance by default, but can be overridden to use
|
|
35
|
+
# a different table context (e.g., for testing or custom implementations).
|
|
36
|
+
# The setter validates that the value responds to both +row+ and +rows+ methods
|
|
37
|
+
# (duck typing for table interface).
|
|
38
|
+
#
|
|
39
|
+
# @return [IS::Term::StatusTable]
|
|
40
|
+
# @raise [ArgumentError] if assigned value does not respond to +row+ and +rows+
|
|
41
|
+
# @!attribute [rw] _table
|
|
42
|
+
|
|
43
|
+
def _table
|
|
44
|
+
@status_table ||= IS::Term::StatusTable::instance
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def _table= value
|
|
48
|
+
raise ArgumentError, "Invalid value for '_table': #{ value.inspect }", caller_locations unless value.respond_to?(:row) && value.respond_to?(:rows)
|
|
49
|
+
@status_table = value
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# @endgroup
|
|
53
|
+
|
|
54
|
+
public
|
|
55
|
+
|
|
56
|
+
# @group Row or Table Functions
|
|
57
|
+
|
|
58
|
+
# Return starting time of row or whole table.
|
|
59
|
+
# @return [Time, nil]
|
|
60
|
+
#
|
|
61
|
+
# @overload started(row)
|
|
62
|
+
# When this row was started.
|
|
63
|
+
# @param [Hash] row the row hash containing +:_started+ key
|
|
64
|
+
#
|
|
65
|
+
# @overload started(id)
|
|
66
|
+
# Find row by id and return when it started. Returns +nil+ if row not found.
|
|
67
|
+
# @param [Object] id the row identifier
|
|
68
|
+
#
|
|
69
|
+
# @overload started
|
|
70
|
+
# When the whole table was started (minimum start time across all rows).
|
|
71
|
+
# Returns +nil+ if table is empty or no rows have started.
|
|
72
|
+
def started row = nil
|
|
73
|
+
if row.is_a?(Hash)
|
|
74
|
+
row[:_started]
|
|
75
|
+
else
|
|
76
|
+
tbl = _table
|
|
77
|
+
if row.nil?
|
|
78
|
+
tbl.rows.map { |r| r[:_started] }.min
|
|
79
|
+
else
|
|
80
|
+
r = tbl.row row
|
|
81
|
+
r.nil? ? nil : started(r)
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# Return finishing time of row or whole table.
|
|
87
|
+
# @return [Time, nil]
|
|
88
|
+
#
|
|
89
|
+
# @overload finished(row)
|
|
90
|
+
# When this row was finished.
|
|
91
|
+
# @param [Hash] row the row hash containing +:_finished+ key
|
|
92
|
+
#
|
|
93
|
+
# @overload finished(id)
|
|
94
|
+
# Find row by id and return when it finished. Returns +nil+ if row not found or not finished
|
|
95
|
+
# @param [Object] id the row identifier
|
|
96
|
+
#
|
|
97
|
+
# @overload finished
|
|
98
|
+
# When the whole table was finished (maximum finish time across all rows).
|
|
99
|
+
# Returns +nil+ if any row is still active (not finished) or table is empty.
|
|
100
|
+
def finished row = nil
|
|
101
|
+
if row.is_a?(Hash)
|
|
102
|
+
row[:_finished]
|
|
103
|
+
else
|
|
104
|
+
tbl = _table
|
|
105
|
+
if row.nil?
|
|
106
|
+
values = tbl.rows.map { |r| r[:_finished] }
|
|
107
|
+
if values.any? { |v| v.nil? }
|
|
108
|
+
nil
|
|
109
|
+
else
|
|
110
|
+
values.max
|
|
111
|
+
end
|
|
112
|
+
else
|
|
113
|
+
r = tbl.row row
|
|
114
|
+
r.nil? ? nil : finished(r)
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
# Return a percent of execution — +(0 .. 100)+.
|
|
120
|
+
#
|
|
121
|
+
# @overload percent(row)
|
|
122
|
+
# Execution percent of row
|
|
123
|
+
# @param [Hash] row
|
|
124
|
+
#
|
|
125
|
+
# @overload percent(id)
|
|
126
|
+
# Execution percent of row with specified id
|
|
127
|
+
# @param [Object] id
|
|
128
|
+
#
|
|
129
|
+
# @overload percent
|
|
130
|
+
# Execution percent of whole table
|
|
131
|
+
#
|
|
132
|
+
# @return [Integer, nil]
|
|
133
|
+
def percent row = nil
|
|
134
|
+
current = self.current row
|
|
135
|
+
total = self.total row
|
|
136
|
+
if current.nil? || total.nil? || total == 0
|
|
137
|
+
nil
|
|
138
|
+
else
|
|
139
|
+
(current * 100) / total
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
# Return estimated remaining execution time is seconds.
|
|
144
|
+
#
|
|
145
|
+
# @overload estimated(row)
|
|
146
|
+
# Estimated remaining time of row execution
|
|
147
|
+
# @param [Hash] row
|
|
148
|
+
#
|
|
149
|
+
# @overload estimated(id)
|
|
150
|
+
# Estimated remaining time of row with specified id
|
|
151
|
+
# @param [Object] id
|
|
152
|
+
#
|
|
153
|
+
# @overload estimated
|
|
154
|
+
# Estimated remaining time of whole table
|
|
155
|
+
#
|
|
156
|
+
# @return [Float, nil] Value in seconds
|
|
157
|
+
def estimated row = nil
|
|
158
|
+
elapsed = self.elapsed row
|
|
159
|
+
current = self.current row
|
|
160
|
+
total = self.total row
|
|
161
|
+
if elapsed.nil? || current.nil? || total.nil? || current == 0
|
|
162
|
+
nil
|
|
163
|
+
else
|
|
164
|
+
(elapsed.to_f / current) * (total - current)
|
|
165
|
+
end
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
# Return elapsed time in seconds.
|
|
169
|
+
#
|
|
170
|
+
# @overload elapsed(row)
|
|
171
|
+
# Elapsed time of row execution
|
|
172
|
+
# @param [Hash] row
|
|
173
|
+
#
|
|
174
|
+
# @overload elapsed(id)
|
|
175
|
+
# Elapsed time of row with specified id
|
|
176
|
+
# @param [Object] id
|
|
177
|
+
#
|
|
178
|
+
# @overload elapsed
|
|
179
|
+
# Elapsed time of whole table
|
|
180
|
+
#
|
|
181
|
+
# @return [Float, nil] Value in seconds
|
|
182
|
+
def elapsed row = nil
|
|
183
|
+
started = self.started row
|
|
184
|
+
finished = self.finished row
|
|
185
|
+
if started.nil?
|
|
186
|
+
nil
|
|
187
|
+
elsif finished.nil?
|
|
188
|
+
Time::now - started
|
|
189
|
+
else
|
|
190
|
+
finished - started
|
|
191
|
+
end
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
# Return average execution speed (steps in second).
|
|
195
|
+
#
|
|
196
|
+
# @overload speed(row)
|
|
197
|
+
# Speed of row execution
|
|
198
|
+
# @param [Hash] row
|
|
199
|
+
#
|
|
200
|
+
# @overload speed(id)
|
|
201
|
+
# Speed of row with specified id
|
|
202
|
+
# @param [Object] id
|
|
203
|
+
#
|
|
204
|
+
# @overload speed
|
|
205
|
+
# Execution speed of whole table
|
|
206
|
+
#
|
|
207
|
+
# @return [Float, nil]
|
|
208
|
+
def speed row = nil
|
|
209
|
+
elapsed = self.elapsed row
|
|
210
|
+
current = self.current row
|
|
211
|
+
finished = self.finished row
|
|
212
|
+
total = self.total row
|
|
213
|
+
if elapsed.nil? || current.nil?
|
|
214
|
+
nil
|
|
215
|
+
else
|
|
216
|
+
if finished && total
|
|
217
|
+
total.to_f / elapsed
|
|
218
|
+
else
|
|
219
|
+
current.to_f / elapsed
|
|
220
|
+
end
|
|
221
|
+
end
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
# Return current steps value for row or whole table.
|
|
225
|
+
#
|
|
226
|
+
# @overload current(row)
|
|
227
|
+
# Current step in specified row
|
|
228
|
+
# @param [Hash] row
|
|
229
|
+
#
|
|
230
|
+
# @overload current(id)
|
|
231
|
+
# Current step in row with specified id
|
|
232
|
+
# @param [Object] id
|
|
233
|
+
#
|
|
234
|
+
# @overload current
|
|
235
|
+
# Sum of current of whole table
|
|
236
|
+
#
|
|
237
|
+
# @return [Integer, nil]
|
|
238
|
+
def current row = nil
|
|
239
|
+
if row.is_a?(Hash)
|
|
240
|
+
row[:current]
|
|
241
|
+
else
|
|
242
|
+
tbl = _table
|
|
243
|
+
if row.nil?
|
|
244
|
+
tbl.rows.map { |r| r[:total] ? r[:current] : nil }.compact.sum
|
|
245
|
+
else
|
|
246
|
+
r = tbl.row row
|
|
247
|
+
r.nil? ? nil : current(r)
|
|
248
|
+
end
|
|
249
|
+
end
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
# Return total steps value of row or table.
|
|
253
|
+
#
|
|
254
|
+
# @overload total(row)
|
|
255
|
+
# Total step count of row
|
|
256
|
+
# @param [Hash] row
|
|
257
|
+
#
|
|
258
|
+
# @overload total(id)
|
|
259
|
+
# Total step count of row with specified id
|
|
260
|
+
# @param [Object] id
|
|
261
|
+
#
|
|
262
|
+
# @overload total
|
|
263
|
+
# Total step count of whole table
|
|
264
|
+
#
|
|
265
|
+
# @return [Integer, nil]
|
|
266
|
+
def total row = nil
|
|
267
|
+
if row.is_a?(Hash)
|
|
268
|
+
row[:total]
|
|
269
|
+
else
|
|
270
|
+
tbl = _table
|
|
271
|
+
if row.nil?
|
|
272
|
+
tbl.rows.map { |r| r[:total] }.compact.sum
|
|
273
|
+
else
|
|
274
|
+
r = tbl.row row
|
|
275
|
+
r.nil? ? nil : total(r)
|
|
276
|
+
end
|
|
277
|
+
end
|
|
278
|
+
end
|
|
279
|
+
|
|
280
|
+
# Is a row or table active?
|
|
281
|
+
#
|
|
282
|
+
# @overload active?(row)
|
|
283
|
+
# Is this row active?
|
|
284
|
+
# @param [Hash] row
|
|
285
|
+
#
|
|
286
|
+
# @overload active?(id)
|
|
287
|
+
# Is row with specified id active?
|
|
288
|
+
# @param [Object] id
|
|
289
|
+
#
|
|
290
|
+
# @overload active?
|
|
291
|
+
# Is any row of table active?
|
|
292
|
+
#
|
|
293
|
+
# @return [Boolean, nil]
|
|
294
|
+
def active? row = nil
|
|
295
|
+
if row.is_a?(Hash)
|
|
296
|
+
row[:_active]
|
|
297
|
+
else
|
|
298
|
+
tbl = _table
|
|
299
|
+
if row.nil?
|
|
300
|
+
tbl.rows.any? { |r| r[:_active] }
|
|
301
|
+
else
|
|
302
|
+
r = tbl.row row
|
|
303
|
+
r.nil? ? nil : active?(r)
|
|
304
|
+
end
|
|
305
|
+
end
|
|
306
|
+
end
|
|
307
|
+
|
|
308
|
+
# Is a row or table done?
|
|
309
|
+
#
|
|
310
|
+
# @overload done?(row)
|
|
311
|
+
# Is this row done?
|
|
312
|
+
# @param [Hash] row
|
|
313
|
+
#
|
|
314
|
+
# @overload done?(id)
|
|
315
|
+
# Is row with specified id done?
|
|
316
|
+
# @param [Object] id
|
|
317
|
+
#
|
|
318
|
+
# @overload done?
|
|
319
|
+
# Is all rows if table done?
|
|
320
|
+
#
|
|
321
|
+
# @return [Boolean, nil]
|
|
322
|
+
def done? row = nil
|
|
323
|
+
active = self.active? row
|
|
324
|
+
active.nil? ? nil : !active
|
|
325
|
+
end
|
|
326
|
+
|
|
327
|
+
# @endgroup
|
|
328
|
+
|
|
329
|
+
# @group Table-only Functions
|
|
330
|
+
|
|
331
|
+
# Count of active rows
|
|
332
|
+
# @return [Integer]
|
|
333
|
+
def active
|
|
334
|
+
tbl = _table
|
|
335
|
+
tbl.rows.select { |r| r[:_active] }.count
|
|
336
|
+
end
|
|
337
|
+
|
|
338
|
+
# Count of done rows
|
|
339
|
+
# @return [Integer]
|
|
340
|
+
def done
|
|
341
|
+
tbl = _table
|
|
342
|
+
tbl.rows.select { |r| !r[:_active] }.count
|
|
343
|
+
end
|
|
344
|
+
|
|
345
|
+
# Is table empty?
|
|
346
|
+
# @return [Boolean]
|
|
347
|
+
def empty?
|
|
348
|
+
self.count == 0
|
|
349
|
+
end
|
|
350
|
+
|
|
351
|
+
# @endgroup
|
|
352
|
+
|
|
353
|
+
# @group Aggregate Functions
|
|
354
|
+
|
|
355
|
+
# Sum of field values
|
|
356
|
+
# @return [Numeric]
|
|
357
|
+
def sum name
|
|
358
|
+
tbl = _table
|
|
359
|
+
tbl.rows.map { |r| r[name] }.compact.sum
|
|
360
|
+
end
|
|
361
|
+
|
|
362
|
+
# Average value of field
|
|
363
|
+
# @return [Numeric, nil]
|
|
364
|
+
def avg name
|
|
365
|
+
tbl = _table
|
|
366
|
+
vls = tbl.rows.map { |r| r[name] }.compact
|
|
367
|
+
sum = vls.sum
|
|
368
|
+
cnt = vls.count
|
|
369
|
+
if cnt == 0
|
|
370
|
+
nil
|
|
371
|
+
else
|
|
372
|
+
sum / cnt
|
|
373
|
+
end
|
|
374
|
+
end
|
|
375
|
+
|
|
376
|
+
# Minimum of field values
|
|
377
|
+
# @return [Comparable, nil]
|
|
378
|
+
def min name
|
|
379
|
+
tbl = _table
|
|
380
|
+
tbl.rows.map { |r| r[name] }.compact.min
|
|
381
|
+
end
|
|
382
|
+
|
|
383
|
+
# Maximum of field values
|
|
384
|
+
# @return [Comparable, nil]
|
|
385
|
+
def max name
|
|
386
|
+
tbl = _table
|
|
387
|
+
tbl.rows.map { |r| r[name] }.compact.max
|
|
388
|
+
end
|
|
389
|
+
|
|
390
|
+
# @endgroup
|
|
391
|
+
|
|
392
|
+
# @group Aggregate or Table Function
|
|
393
|
+
|
|
394
|
+
# Count of rows, See Details.
|
|
395
|
+
#
|
|
396
|
+
# @overload cnt(name)
|
|
397
|
+
# Count of unique not null values of field
|
|
398
|
+
# @param [Symbol] name
|
|
399
|
+
#
|
|
400
|
+
# @overload count
|
|
401
|
+
# Count of rows
|
|
402
|
+
#
|
|
403
|
+
# @return [Integer]
|
|
404
|
+
def count name = nil
|
|
405
|
+
rows = _table.rows
|
|
406
|
+
if name.nil?
|
|
407
|
+
rows.count
|
|
408
|
+
else
|
|
409
|
+
rows.map { |r| r[name] }.compact.uniq.count
|
|
410
|
+
end
|
|
411
|
+
end
|
|
412
|
+
|
|
413
|
+
alias :cnt :count
|
|
414
|
+
|
|
415
|
+
# @endgroup
|
|
416
|
+
|
|
417
|
+
extend self
|
|
418
|
+
|
|
419
|
+
# @api private
|
|
420
|
+
ROW_METHODS = [ :started, :finished, :percent, :estimated, :elapsed, :speed, :current, :total, :active?, :done? ].freeze
|
|
421
|
+
|
|
422
|
+
# @api private
|
|
423
|
+
TABLE_METHODS = [ :started, :finished, :percent, :estimated, :elapsed, :speed, :current, :total, :active, :active?, :done, :done?, :count, :empty? ].freeze
|
|
424
|
+
|
|
425
|
+
# @api private
|
|
426
|
+
AGGREGATE_METHODS = [ :sum, :avg, :min, :max, :cnt, :count ].freeze
|
|
427
|
+
|
|
428
|
+
class << self
|
|
429
|
+
|
|
430
|
+
# @group Function Access
|
|
431
|
+
|
|
432
|
+
# @return [Proc]
|
|
433
|
+
def row_func method_name
|
|
434
|
+
raise NameError, "Invalid function name: #{ method_name.inspect }", caller_locations unless ROW_METHODS.include?(method_name)
|
|
435
|
+
self.method(method_name).to_proc
|
|
436
|
+
end
|
|
437
|
+
|
|
438
|
+
# @return [Proc]
|
|
439
|
+
def table_func method_name
|
|
440
|
+
raise NameError, "Invalid function name: #{ method_name.inspect }", caller_locations unless TABLE_METHODS.include?(method_name)
|
|
441
|
+
meth = self.method method_name
|
|
442
|
+
if ROW_METHODS.include?(method_name) || AGGREGATE_METHODS.include?(method_name)
|
|
443
|
+
lambda { meth.call(nil) }
|
|
444
|
+
else
|
|
445
|
+
meth.to_proc
|
|
446
|
+
end
|
|
447
|
+
end
|
|
448
|
+
|
|
449
|
+
# @return [Proc]
|
|
450
|
+
def aggregate_func method_name, field_name
|
|
451
|
+
raise NameError, "Invalid function name: #{ method_name.inspect }", caller_locations unless AGGREGATE_METHODS.include?(method_name)
|
|
452
|
+
meth = self.method method_name
|
|
453
|
+
lambda { meth.call(field_name) }
|
|
454
|
+
end
|
|
455
|
+
|
|
456
|
+
alias :RF :row_func
|
|
457
|
+
alias :TF :table_func
|
|
458
|
+
alias :AF :aggregate_func
|
|
459
|
+
|
|
460
|
+
# @endgroup
|
|
461
|
+
|
|
462
|
+
end
|
|
463
|
+
|
|
464
|
+
end
|
|
465
|
+
|
|
466
|
+
class IS::Term::StatusTable
|
|
467
|
+
include IS::Term::StatusTable::Functions
|
|
468
|
+
|
|
469
|
+
protected
|
|
470
|
+
|
|
471
|
+
# @private
|
|
472
|
+
def _table
|
|
473
|
+
self
|
|
474
|
+
end
|
|
475
|
+
|
|
476
|
+
end
|
data/lib/is-term/info.rb
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module IS; end
|
|
4
|
+
|
|
5
|
+
module IS::Term; end
|
|
6
|
+
|
|
7
|
+
module IS::Term::Info
|
|
8
|
+
|
|
9
|
+
NAME = 'is-term'
|
|
10
|
+
VERSION = '0.8.0'
|
|
11
|
+
AUTHOR = "Ivan Shikhalev"
|
|
12
|
+
AUTHOR_URL = "https://github.com/shikhalev"
|
|
13
|
+
EMAIL = "shikhalev@gmail.com"
|
|
14
|
+
|
|
15
|
+
LICENSE = "GPL-3.0-or-later"
|
|
16
|
+
LICENSE_URL = "https://github.com/inat-get/is-term/blob/main/LICENSE"
|
|
17
|
+
|
|
18
|
+
SUMMARY = "Terminal utilities for Ruby scripts"
|
|
19
|
+
DESCRIPTION = "Terminal utilities for Ruby scripts."
|
|
20
|
+
|
|
21
|
+
HOMEPAGE = "https://github.com/inat-get/is-term"
|
|
22
|
+
|
|
23
|
+
end
|