tatum 1.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/README.md +59 -0
- data/lib/tatum.rb +952 -0
- metadata +58 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 6ca82f0b4d48158ed5310314fcd8d210e5c9621262867cc02fe86e094d794d93
|
4
|
+
data.tar.gz: ef7dc790d299b6c19b691cbd88ec82fc42df49e95f33c930865267d89fc8fdd0
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 610c3f0d20bcf3f755c7e95788b56a0b4c6d2744a74f1f5bd722c1b06b09c921e13693fe651efa203dd31b2a470237075514f37ca5e21f43f3a96b4bf72575c6
|
7
|
+
data.tar.gz: 318fcce30f9628926b2022bc6331e873f75dceefa9996bfd08dd94f96eca3a4bf6590688573cac809efe8ce74c48bcbcc2ea8a6399345204e503f48626827a71
|
data/README.md
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
# Tatum
|
2
|
+
Ruby utility for outputting info to STDOUT, STDERR, a string, or a file.
|
3
|
+
|
4
|
+
|
5
|
+
## Install
|
6
|
+
|
7
|
+
The usual:
|
8
|
+
|
9
|
+
```
|
10
|
+
gem install tatum
|
11
|
+
```
|
12
|
+
|
13
|
+
## Use
|
14
|
+
|
15
|
+
Everything is done with the TTM module. In the simplest use, use `TTM.puts` to
|
16
|
+
output any string:
|
17
|
+
|
18
|
+
```ruby
|
19
|
+
TTM.puts 'whatever'
|
20
|
+
```
|
21
|
+
|
22
|
+
By default (and by design) TTM doesn't actually output anything to anywhere.
|
23
|
+
So without further configuration, the command above wouldn't do anything. That
|
24
|
+
feature allows you to pepper your code with `TTM.puts` commands without having to
|
25
|
+
constantly do commands like this:
|
26
|
+
|
27
|
+
```ruby
|
28
|
+
if verbose
|
29
|
+
puts 'whatever'
|
30
|
+
end
|
31
|
+
```
|
32
|
+
|
33
|
+
To set output, use one of the following commands:
|
34
|
+
|
35
|
+
```ruby
|
36
|
+
TTM.io = STDOUT # output to STDOUT
|
37
|
+
TTM.io = STDERR # output to STDERR
|
38
|
+
TTM.io = './path.txt' # output to a file
|
39
|
+
TTM.io = TTM::Cache.new # output to a stringifiable object
|
40
|
+
```
|
41
|
+
|
42
|
+
You can also set TTM back to not outputting to anything:
|
43
|
+
|
44
|
+
```ruby
|
45
|
+
TTM.io = nil # don't output to anything
|
46
|
+
```
|
47
|
+
|
48
|
+
See the documentation in talk-to-me.rb for details.
|
49
|
+
|
50
|
+
## Author
|
51
|
+
|
52
|
+
Mike O'Sullivan
|
53
|
+
mike@idocs.com
|
54
|
+
|
55
|
+
## History
|
56
|
+
|
57
|
+
| version | date | notes |
|
58
|
+
|----------|--------------|-----------------|
|
59
|
+
| 1.0 | May 18, 2023 | Initial upload. |
|
data/lib/tatum.rb
ADDED
@@ -0,0 +1,952 @@
|
|
1
|
+
#===============================================================================
|
2
|
+
# TTM
|
3
|
+
#
|
4
|
+
module TTM
|
5
|
+
# initialize attributes
|
6
|
+
@indent = 0
|
7
|
+
@io = nil
|
8
|
+
@hr_width = 50
|
9
|
+
@tab = ' '
|
10
|
+
|
11
|
+
|
12
|
+
#---------------------------------------------------------------------------
|
13
|
+
# accessors
|
14
|
+
#
|
15
|
+
|
16
|
+
# Returns @io
|
17
|
+
def self.io
|
18
|
+
return @io
|
19
|
+
end
|
20
|
+
|
21
|
+
# Sets the output handle. Usually you'll want to set the handle to STDOUT or
|
22
|
+
# STDERR. If the given io is a string, it's assumed to be the path to a file
|
23
|
+
# to write to. To write to a string in memory, send TTM::Memory.
|
24
|
+
#
|
25
|
+
# If a Class object is sent, then the class is instantiated with the p_io
|
26
|
+
# as the param for new(). That class will have to provide the #puts method.
|
27
|
+
def self.io=(p_io)
|
28
|
+
# special case: if p_io is a string, instantiate a TTM::File object.
|
29
|
+
if p_io.is_a?(String)
|
30
|
+
return @io = TTM::File.new(p_io)
|
31
|
+
|
32
|
+
# if the given object is a class, instantiate it
|
33
|
+
elsif p_io.is_a?(Class)
|
34
|
+
return @io = p_io.new(p_io)
|
35
|
+
|
36
|
+
# else just hold on to the handle
|
37
|
+
else
|
38
|
+
return @io = p_io
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# Returns width of horizontal rule.
|
43
|
+
# @return [Int]
|
44
|
+
def self.hr_width
|
45
|
+
return @hr_width
|
46
|
+
end
|
47
|
+
|
48
|
+
# Sets width of horizontal rule.
|
49
|
+
# @param [Int] p_width
|
50
|
+
# @return [Int]
|
51
|
+
def self.hr_width=(p_width)
|
52
|
+
return @hr_width = p_width
|
53
|
+
end
|
54
|
+
|
55
|
+
# Returns the string used for indentation.
|
56
|
+
#
|
57
|
+
# @return [String]
|
58
|
+
def self.tab
|
59
|
+
return @tab
|
60
|
+
end
|
61
|
+
|
62
|
+
# Sets the tab used for indentation
|
63
|
+
#
|
64
|
+
# TTM.tab = ' '
|
65
|
+
#
|
66
|
+
# TTM.indent('[a]') do
|
67
|
+
# TTM.puts '[b]'
|
68
|
+
# end
|
69
|
+
#
|
70
|
+
# TTM.puts '[c]'
|
71
|
+
#
|
72
|
+
# outputs:
|
73
|
+
#
|
74
|
+
# [a]
|
75
|
+
# [b]
|
76
|
+
# [c]
|
77
|
+
#
|
78
|
+
# @param [String] p_tab
|
79
|
+
# @return [String]
|
80
|
+
def self.tab=(p_tab)
|
81
|
+
return @tab = p_tab
|
82
|
+
end
|
83
|
+
|
84
|
+
#
|
85
|
+
# accessors
|
86
|
+
#---------------------------------------------------------------------------
|
87
|
+
|
88
|
+
|
89
|
+
#---------------------------------------------------------------------------
|
90
|
+
# puts
|
91
|
+
#
|
92
|
+
|
93
|
+
# Outputs a stringification of the given object, indented if necessary.
|
94
|
+
#
|
95
|
+
# TTM.puts '[a]'
|
96
|
+
#
|
97
|
+
# TTM.indent do
|
98
|
+
# line = "[b]\n[c]\n[d]"
|
99
|
+
# TTM.puts line
|
100
|
+
# end
|
101
|
+
#
|
102
|
+
# TTM.puts '[e]'
|
103
|
+
#
|
104
|
+
# outputs:
|
105
|
+
#
|
106
|
+
# [a]
|
107
|
+
# [b]
|
108
|
+
# [c]
|
109
|
+
# [d]
|
110
|
+
# [e]
|
111
|
+
#
|
112
|
+
# Some objects are represented by strings in brackets instead of their
|
113
|
+
# to_s values. This is to make it easier to see what typew of objects they
|
114
|
+
# are.
|
115
|
+
#
|
116
|
+
# TTM.puts nil
|
117
|
+
# TTM.puts ''
|
118
|
+
# TTM.puts ' '
|
119
|
+
#
|
120
|
+
# outputs:
|
121
|
+
#
|
122
|
+
# [nil]
|
123
|
+
# [empty-string]
|
124
|
+
# [no-content-string]
|
125
|
+
|
126
|
+
def self.puts(*opts)
|
127
|
+
@io or return
|
128
|
+
lead = @tab * @indent
|
129
|
+
vals = []
|
130
|
+
|
131
|
+
# build string values
|
132
|
+
opts.each do |opt|
|
133
|
+
vals.push object_display_string(opt)
|
134
|
+
end
|
135
|
+
|
136
|
+
# loop through strings
|
137
|
+
vals.join('').lines.each do |line|
|
138
|
+
line = lead + line
|
139
|
+
@io.puts line
|
140
|
+
end
|
141
|
+
|
142
|
+
|
143
|
+
# Always return nil to avoid confusion when this method is the last line
|
144
|
+
# in a function and the return value of the function is used for
|
145
|
+
# something.
|
146
|
+
return nil
|
147
|
+
end
|
148
|
+
#
|
149
|
+
# puts
|
150
|
+
#---------------------------------------------------------------------------
|
151
|
+
|
152
|
+
|
153
|
+
#---------------------------------------------------------------------------
|
154
|
+
# clear
|
155
|
+
#
|
156
|
+
|
157
|
+
# Clears the output handle. If @io is STDOUT or STDERR, this method does
|
158
|
+
# nothing. If @io is a String, deletes the file at that path if it exists.
|
159
|
+
# If @io is any other object that responds to #clear then that method is
|
160
|
+
# called.
|
161
|
+
#
|
162
|
+
# @return [nil]
|
163
|
+
def self.clear
|
164
|
+
if @io.respond_to?('clear')
|
165
|
+
@io.clear
|
166
|
+
end
|
167
|
+
end
|
168
|
+
#
|
169
|
+
# clear
|
170
|
+
#---------------------------------------------------------------------------
|
171
|
+
|
172
|
+
|
173
|
+
#---------------------------------------------------------------------------
|
174
|
+
# indent
|
175
|
+
#
|
176
|
+
|
177
|
+
# Sets an indentation level. Output within the do block is indented. Takes
|
178
|
+
# an optional string.
|
179
|
+
#
|
180
|
+
# TTM.indent('whatever') do
|
181
|
+
# TTM.puts 'dude'
|
182
|
+
# end
|
183
|
+
#
|
184
|
+
# outputs:
|
185
|
+
#
|
186
|
+
# whatever
|
187
|
+
# dude
|
188
|
+
|
189
|
+
def self.indent(*opts)
|
190
|
+
opts = opts_to_hash(*opts)
|
191
|
+
|
192
|
+
# output header if one was sent
|
193
|
+
if opts['str']
|
194
|
+
puts opts['str']
|
195
|
+
end
|
196
|
+
|
197
|
+
# if block given, temporarily set indent, then revert
|
198
|
+
if block_given?
|
199
|
+
hold_indent = @indent
|
200
|
+
|
201
|
+
unless opts['skip']
|
202
|
+
@indent += 1
|
203
|
+
end
|
204
|
+
|
205
|
+
begin
|
206
|
+
yield
|
207
|
+
ensure
|
208
|
+
@indent = hold_indent
|
209
|
+
end
|
210
|
+
|
211
|
+
# else just set indent
|
212
|
+
else
|
213
|
+
@indent += 1
|
214
|
+
end
|
215
|
+
end
|
216
|
+
#
|
217
|
+
# indent
|
218
|
+
#---------------------------------------------------------------------------
|
219
|
+
|
220
|
+
|
221
|
+
#---------------------------------------------------------------------------
|
222
|
+
# tmp_io
|
223
|
+
#
|
224
|
+
|
225
|
+
# Temporarily sends output to a different output target in the do block.
|
226
|
+
#
|
227
|
+
# TTM.indent('[a]') do
|
228
|
+
# TTM.puts '[stuff sent to STDOUT]'
|
229
|
+
#
|
230
|
+
# TTM.tmp_io(STDERR) do
|
231
|
+
# TTM.puts '[stuff sent to STDERR]'
|
232
|
+
# end
|
233
|
+
#
|
234
|
+
# TTM.puts '[more stuff sent to STDOUT]'
|
235
|
+
# end
|
236
|
+
#
|
237
|
+
# This code outputs this to STDOUT:
|
238
|
+
#
|
239
|
+
# [a]
|
240
|
+
# [stuff sent to STDOUT]
|
241
|
+
# [more stuff sent to STDOUT]
|
242
|
+
#
|
243
|
+
# And this to STDERR. Notice that indentation is reset to 0 during the temporary
|
244
|
+
# redirect.
|
245
|
+
#
|
246
|
+
# [stuff sent to STDERR]
|
247
|
+
|
248
|
+
def self.tmp_io(p_io, &block)
|
249
|
+
io_hold = @io
|
250
|
+
@io = p_io
|
251
|
+
hold_indent = @indent
|
252
|
+
@indent = 0
|
253
|
+
yield
|
254
|
+
ensure
|
255
|
+
@indent = hold_indent
|
256
|
+
@io = io_hold
|
257
|
+
end
|
258
|
+
#
|
259
|
+
# silent
|
260
|
+
#---------------------------------------------------------------------------
|
261
|
+
|
262
|
+
|
263
|
+
#---------------------------------------------------------------------------
|
264
|
+
# silent
|
265
|
+
#
|
266
|
+
|
267
|
+
# Temporarily turns off output.
|
268
|
+
#
|
269
|
+
# TTM.puts '[a]'
|
270
|
+
#
|
271
|
+
# TTM.silent do
|
272
|
+
# TTM.puts '[b]'
|
273
|
+
# end
|
274
|
+
#
|
275
|
+
# TTM.puts '[c]'
|
276
|
+
#
|
277
|
+
# outputs:
|
278
|
+
#
|
279
|
+
# [a]
|
280
|
+
# [c]
|
281
|
+
|
282
|
+
def self.silent(&block)
|
283
|
+
tmp_io nil, &block
|
284
|
+
end
|
285
|
+
#
|
286
|
+
# silent
|
287
|
+
#---------------------------------------------------------------------------
|
288
|
+
|
289
|
+
|
290
|
+
#---------------------------------------------------------------------------
|
291
|
+
# show
|
292
|
+
#
|
293
|
+
|
294
|
+
# TTM.show outputs a visual representation of a hash or an array.
|
295
|
+
#
|
296
|
+
# hsh = {
|
297
|
+
# 'whatever' => 'dude',
|
298
|
+
# 'people' => [
|
299
|
+
# 'Joe',
|
300
|
+
# 'Mekonnan',
|
301
|
+
# ''
|
302
|
+
# ],
|
303
|
+
#
|
304
|
+
# 'status' => nil
|
305
|
+
# };
|
306
|
+
#
|
307
|
+
# TTM.show hsh
|
308
|
+
#
|
309
|
+
# arr = %w{a b c}
|
310
|
+
# TTM.show arr
|
311
|
+
#
|
312
|
+
# outputs:
|
313
|
+
#
|
314
|
+
# +----------+---------------------+
|
315
|
+
# | people | [Joe | Mekonnan | ] |
|
316
|
+
# | status | [nil] |
|
317
|
+
# | whatever | dude |
|
318
|
+
# +----------+---------------------+
|
319
|
+
# --------------------------------------------------
|
320
|
+
# a
|
321
|
+
# b
|
322
|
+
# c
|
323
|
+
# --------------------------------------------------
|
324
|
+
|
325
|
+
def self.show(obj)
|
326
|
+
@io or return
|
327
|
+
return TTM::Show.puts obj
|
328
|
+
end
|
329
|
+
#
|
330
|
+
# show
|
331
|
+
#---------------------------------------------------------------------------
|
332
|
+
|
333
|
+
|
334
|
+
#---------------------------------------------------------------------------
|
335
|
+
# hr
|
336
|
+
#
|
337
|
+
|
338
|
+
# Outputs a horizontal rule.
|
339
|
+
# TTM.hr
|
340
|
+
#
|
341
|
+
# gives us this:
|
342
|
+
# --------------------------------------------------
|
343
|
+
#
|
344
|
+
# If you pass in a string, that string is embedded in the horizontal rule.
|
345
|
+
# TTM.hr 'whatever'
|
346
|
+
# gives us this:
|
347
|
+
# --- whatever -------------------------------------
|
348
|
+
#
|
349
|
+
# TTM.hr takes a block param. If a block is sent, then a horizontal rule is
|
350
|
+
# output before and after the block:
|
351
|
+
#
|
352
|
+
# TTM.hr do
|
353
|
+
# puts 'do stuff'
|
354
|
+
# end
|
355
|
+
#
|
356
|
+
# gives us this:
|
357
|
+
#
|
358
|
+
# --------------------------------------------------
|
359
|
+
# do stuff
|
360
|
+
# --------------------------------------------------
|
361
|
+
#
|
362
|
+
# You can combine sending a string and a block:
|
363
|
+
#
|
364
|
+
# TTM.hr('whatever') do
|
365
|
+
# puts 'do stuff'
|
366
|
+
# end
|
367
|
+
#
|
368
|
+
# output:
|
369
|
+
#
|
370
|
+
# --- whatever -------------------------------------
|
371
|
+
# do stuff
|
372
|
+
# --------------------------------------------------
|
373
|
+
#
|
374
|
+
# == opts as hash
|
375
|
+
#
|
376
|
+
# Options can be passed in as a hash. Behind the scenes, if you pass in a
|
377
|
+
# string then it is converted to a hash like this:
|
378
|
+
#
|
379
|
+
# {'title'=>'whatever'}
|
380
|
+
#
|
381
|
+
# So these two commands do exactly the same thing:
|
382
|
+
#
|
383
|
+
# TTM.hr 'whatever'
|
384
|
+
# TTM.hr 'title'=>'whatever'
|
385
|
+
#
|
386
|
+
# === dash
|
387
|
+
#
|
388
|
+
# The dash option indicates what character to use for the dashes in the
|
389
|
+
# horizontal rule.
|
390
|
+
#
|
391
|
+
# TTM.hr 'title'=>'whatever', 'dash'=>'='
|
392
|
+
#
|
393
|
+
# output:
|
394
|
+
#
|
395
|
+
# === whatever =====================================
|
396
|
+
|
397
|
+
def self.hr(opts=nil, &block)
|
398
|
+
@io or return
|
399
|
+
return TTM::HR.puts opts, &block
|
400
|
+
end
|
401
|
+
#
|
402
|
+
# hr
|
403
|
+
#---------------------------------------------------------------------------
|
404
|
+
|
405
|
+
|
406
|
+
#---------------------------------------------------------------------------
|
407
|
+
# hrm
|
408
|
+
#
|
409
|
+
|
410
|
+
# Outputs the name of the current method in a horizontal rule.
|
411
|
+
#
|
412
|
+
# def mymethod
|
413
|
+
# TTM.hrm
|
414
|
+
# end
|
415
|
+
#
|
416
|
+
# mymethod()
|
417
|
+
#
|
418
|
+
# outputs:
|
419
|
+
#
|
420
|
+
# --- mymethod -------------------------------------
|
421
|
+
#
|
422
|
+
# TTM.hrm accepts a do block:
|
423
|
+
#
|
424
|
+
# def mymethod
|
425
|
+
# TTM.hrm do
|
426
|
+
# puts 'stuff about mymethod'
|
427
|
+
# end
|
428
|
+
# end
|
429
|
+
#
|
430
|
+
# outputs:
|
431
|
+
#
|
432
|
+
# --- mymethod -------------------------------------
|
433
|
+
# stuff about mymethod
|
434
|
+
# --------------------------------------------------
|
435
|
+
|
436
|
+
def self.hrm(*opts)
|
437
|
+
lbl = caller_locations(1,1)[0].label
|
438
|
+
|
439
|
+
if opts[0]
|
440
|
+
lbl += ': ' + opts[0].to_s
|
441
|
+
end
|
442
|
+
|
443
|
+
# block or straight
|
444
|
+
if block_given?
|
445
|
+
self.hr(lbl) do
|
446
|
+
yield
|
447
|
+
end
|
448
|
+
else
|
449
|
+
self.hr lbl
|
450
|
+
end
|
451
|
+
end
|
452
|
+
#
|
453
|
+
# hrm
|
454
|
+
#---------------------------------------------------------------------------
|
455
|
+
|
456
|
+
|
457
|
+
#---------------------------------------------------------------------------
|
458
|
+
# line
|
459
|
+
|
460
|
+
# Outputs the number and file name of the line this method is called from.
|
461
|
+
# Also outputs a given string if one is sent.
|
462
|
+
#
|
463
|
+
# TTM.line 'whatever'
|
464
|
+
#
|
465
|
+
# outputs:
|
466
|
+
#
|
467
|
+
# [6 myfile.rb] whatever
|
468
|
+
|
469
|
+
def self.line(*opts)
|
470
|
+
@io or return
|
471
|
+
opts = opts_to_hash(*opts)
|
472
|
+
opts = {'stack'=>0}.merge(opts)
|
473
|
+
|
474
|
+
# get caller location
|
475
|
+
loc = caller_locations()[opts['stack']]
|
476
|
+
|
477
|
+
# initialize output string
|
478
|
+
out = "[#{loc.lineno} #{File.basename(loc.path)}"
|
479
|
+
|
480
|
+
# add included string if sent
|
481
|
+
if opts['include']
|
482
|
+
out += ' ' + opts['include']
|
483
|
+
end
|
484
|
+
|
485
|
+
# close brackets
|
486
|
+
out += ']'
|
487
|
+
|
488
|
+
# add str if sent
|
489
|
+
if opts['str']
|
490
|
+
out += ' ' + opts['str']
|
491
|
+
end
|
492
|
+
|
493
|
+
# output
|
494
|
+
return self.puts(out)
|
495
|
+
end
|
496
|
+
#
|
497
|
+
# line
|
498
|
+
#---------------------------------------------------------------------------
|
499
|
+
|
500
|
+
|
501
|
+
#---------------------------------------------------------------------------
|
502
|
+
# devexit
|
503
|
+
#
|
504
|
+
|
505
|
+
# Outputs "[devexit]" and exits. This method is handy is testing for when
|
506
|
+
# you want to exit the program, but make it clear that you did so in a
|
507
|
+
# developmentish way.
|
508
|
+
# @return [nothing]
|
509
|
+
def self.devexit(*opts)
|
510
|
+
opts = opts_to_hash(*opts)
|
511
|
+
opts = {'include'=>'devexit', 'stack'=>1}.merge(opts)
|
512
|
+
self.line opts
|
513
|
+
exit
|
514
|
+
end
|
515
|
+
#
|
516
|
+
# devexit
|
517
|
+
#---------------------------------------------------------------------------
|
518
|
+
|
519
|
+
|
520
|
+
#---------------------------------------------------------------------------
|
521
|
+
# json
|
522
|
+
#
|
523
|
+
|
524
|
+
# Outputs a given structure in JSON format;
|
525
|
+
#
|
526
|
+
# hsh = {
|
527
|
+
# 'whatever' => 'dude',
|
528
|
+
# 'people' => [
|
529
|
+
# 'Joe',
|
530
|
+
# 'Mekonnan',
|
531
|
+
# 'AJ'
|
532
|
+
# ]
|
533
|
+
# };
|
534
|
+
#
|
535
|
+
# TTM.json hsh
|
536
|
+
#
|
537
|
+
# outputs
|
538
|
+
#
|
539
|
+
# --------------------------------------------------
|
540
|
+
# {
|
541
|
+
# "whatever": "dude",
|
542
|
+
# "people": [
|
543
|
+
# "Joe",
|
544
|
+
# "Mekonnan",
|
545
|
+
# "AJ"
|
546
|
+
# ]
|
547
|
+
# }
|
548
|
+
# --------------------------------------------------
|
549
|
+
|
550
|
+
def self.json(obj, opts={})
|
551
|
+
@io or return
|
552
|
+
require 'json'
|
553
|
+
|
554
|
+
hr do
|
555
|
+
return self.puts(::JSON.pretty_generate(obj))
|
556
|
+
end
|
557
|
+
end
|
558
|
+
#
|
559
|
+
# json
|
560
|
+
#---------------------------------------------------------------------------
|
561
|
+
|
562
|
+
|
563
|
+
# private
|
564
|
+
private
|
565
|
+
|
566
|
+
#---------------------------------------------------------------------------
|
567
|
+
# opts_to_hash
|
568
|
+
# Figures out if the given opts are nil, a string, or a hash. Always returns
|
569
|
+
# a hash.
|
570
|
+
#
|
571
|
+
# Remember, *opts is always an array.
|
572
|
+
#
|
573
|
+
# If empty array, return empty hash.
|
574
|
+
#
|
575
|
+
# Get first element
|
576
|
+
# If hash, return that
|
577
|
+
# Everything else, return a hash with a stringification of that first
|
578
|
+
# object.
|
579
|
+
#
|
580
|
+
def self.opts_to_hash(*opts)
|
581
|
+
# if opts is empty, return an empty hash
|
582
|
+
if opts.empty?
|
583
|
+
return {}
|
584
|
+
end
|
585
|
+
|
586
|
+
# first element is all we care about
|
587
|
+
el = opts[0]
|
588
|
+
|
589
|
+
# if opts is a hash, return that
|
590
|
+
if el.is_a?(Hash)
|
591
|
+
return opts[0]
|
592
|
+
end
|
593
|
+
|
594
|
+
# everything else, return stringified object as "str" element in hash
|
595
|
+
return {'str'=>object_display_string(el)}
|
596
|
+
end
|
597
|
+
#
|
598
|
+
# opts_to_hash
|
599
|
+
#---------------------------------------------------------------------------
|
600
|
+
|
601
|
+
|
602
|
+
#---------------------------------------------------------------------------
|
603
|
+
# object_display_string
|
604
|
+
# Returns a human readable representation of an object. Note that this
|
605
|
+
# method is basically a shiny gloss over to_s. Don't confuse this method
|
606
|
+
# with showing a hash or array.
|
607
|
+
#
|
608
|
+
def self.object_display_string(obj)
|
609
|
+
# nil
|
610
|
+
if obj.nil?
|
611
|
+
return '[nil]'
|
612
|
+
|
613
|
+
# string values
|
614
|
+
elsif obj.is_a?(String)
|
615
|
+
if obj.match(/\S/mu)
|
616
|
+
return obj
|
617
|
+
elsif obj.empty?
|
618
|
+
return '[empty-string]'
|
619
|
+
else
|
620
|
+
return '[no-content-string]'
|
621
|
+
end
|
622
|
+
|
623
|
+
# else return stringification of object
|
624
|
+
else
|
625
|
+
return obj.to_s
|
626
|
+
end
|
627
|
+
end
|
628
|
+
#
|
629
|
+
# object_display_string
|
630
|
+
#---------------------------------------------------------------------------
|
631
|
+
end
|
632
|
+
#
|
633
|
+
# TTM
|
634
|
+
#===============================================================================
|
635
|
+
|
636
|
+
|
637
|
+
#===============================================================================
|
638
|
+
# TTM::HR
|
639
|
+
#
|
640
|
+
|
641
|
+
# Handles building horizontal rules.
|
642
|
+
|
643
|
+
module TTM::HR
|
644
|
+
#---------------------------------------------------------------------------
|
645
|
+
# puts
|
646
|
+
#
|
647
|
+
|
648
|
+
# Builds and outputs a horizontal rule. See TTM.hr for details.
|
649
|
+
|
650
|
+
def self.puts(opts=nil, &block)
|
651
|
+
opts = parse_opts(opts)
|
652
|
+
dash = opts['dash']
|
653
|
+
|
654
|
+
# output with title or plain
|
655
|
+
if opts['title']
|
656
|
+
out = dash * 3
|
657
|
+
out += ' '
|
658
|
+
out += opts['title']
|
659
|
+
out += ' '
|
660
|
+
out += dash * (TTM.hr_width - out.length)
|
661
|
+
TTM.puts out
|
662
|
+
else
|
663
|
+
TTM.puts dash * TTM.hr_width
|
664
|
+
end
|
665
|
+
|
666
|
+
# if block given, yield and output another hr
|
667
|
+
if block_given?
|
668
|
+
begin
|
669
|
+
yield
|
670
|
+
ensure
|
671
|
+
TTM.puts dash * TTM.hr_width
|
672
|
+
end
|
673
|
+
end
|
674
|
+
|
675
|
+
# always return nil
|
676
|
+
return nil
|
677
|
+
end
|
678
|
+
#
|
679
|
+
# puts
|
680
|
+
#---------------------------------------------------------------------------
|
681
|
+
|
682
|
+
|
683
|
+
#---------------------------------------------------------------------------
|
684
|
+
# parse_opts
|
685
|
+
#
|
686
|
+
|
687
|
+
# Parses the options sent to .puts
|
688
|
+
|
689
|
+
def self.parse_opts(opts=nil)
|
690
|
+
# default
|
691
|
+
default = {'dash'=>'-'}
|
692
|
+
|
693
|
+
# nil
|
694
|
+
if opts.nil?
|
695
|
+
return default
|
696
|
+
end
|
697
|
+
|
698
|
+
# if opts is not a hash, use that object as the title
|
699
|
+
if not opts.is_a?(Hash)
|
700
|
+
opts = {'title'=>opts.to_s}
|
701
|
+
end
|
702
|
+
|
703
|
+
# merge into default
|
704
|
+
opts = default.merge(opts)
|
705
|
+
|
706
|
+
# return
|
707
|
+
return opts
|
708
|
+
end
|
709
|
+
#
|
710
|
+
# parse_opts
|
711
|
+
#---------------------------------------------------------------------------
|
712
|
+
end
|
713
|
+
#
|
714
|
+
# TTM::HR
|
715
|
+
#===============================================================================
|
716
|
+
|
717
|
+
|
718
|
+
#===============================================================================
|
719
|
+
# TTM::Show
|
720
|
+
#
|
721
|
+
|
722
|
+
# Builds the string representation of the given object. See TTM.show for
|
723
|
+
# details.
|
724
|
+
|
725
|
+
module TTM::Show
|
726
|
+
#---------------------------------------------------------------------------
|
727
|
+
# puts
|
728
|
+
#
|
729
|
+
|
730
|
+
# Determines the class of the given object and outputs a string
|
731
|
+
# representation of it using TTM.puts.
|
732
|
+
|
733
|
+
def self.puts(obj, opts={})
|
734
|
+
# nil
|
735
|
+
if obj.nil?
|
736
|
+
TTM.puts '[nil]'
|
737
|
+
|
738
|
+
# hash
|
739
|
+
elsif obj.is_a?(Hash)
|
740
|
+
show_hash obj, opts
|
741
|
+
|
742
|
+
# array
|
743
|
+
elsif obj.is_a?(Array)
|
744
|
+
show_array obj, opts
|
745
|
+
|
746
|
+
# else just output
|
747
|
+
else
|
748
|
+
TTM.puts obj.to_s
|
749
|
+
end
|
750
|
+
|
751
|
+
# always return nil
|
752
|
+
return nil
|
753
|
+
end
|
754
|
+
#
|
755
|
+
# puts
|
756
|
+
#---------------------------------------------------------------------------
|
757
|
+
|
758
|
+
|
759
|
+
#---------------------------------------------------------------------------
|
760
|
+
# show_array
|
761
|
+
#
|
762
|
+
|
763
|
+
# Outputs a string representation of each object in the array. Puts the
|
764
|
+
# output inside horizontal rules.
|
765
|
+
|
766
|
+
def self.show_array(myarr, opts)
|
767
|
+
# if empty
|
768
|
+
if myarr.empty?
|
769
|
+
TTM.puts '[empty array]'
|
770
|
+
|
771
|
+
# else there's stuff in the array
|
772
|
+
else
|
773
|
+
TTM.hr do
|
774
|
+
myarr.each do |el|
|
775
|
+
TTM.puts el
|
776
|
+
end
|
777
|
+
end
|
778
|
+
end
|
779
|
+
end
|
780
|
+
#
|
781
|
+
# show_array
|
782
|
+
#---------------------------------------------------------------------------
|
783
|
+
|
784
|
+
|
785
|
+
#---------------------------------------------------------------------------
|
786
|
+
# show_hash
|
787
|
+
#
|
788
|
+
|
789
|
+
# Outputs a hash as a text table.
|
790
|
+
|
791
|
+
def self.show_hash(hsh, opts)
|
792
|
+
opts = {'sort'=>true}.merge(opts)
|
793
|
+
|
794
|
+
# if empty, output string indicating so
|
795
|
+
if hsh.empty?
|
796
|
+
TTM.puts '[empty hash]'
|
797
|
+
|
798
|
+
# else display hash as a table
|
799
|
+
else
|
800
|
+
require 'text-table'
|
801
|
+
|
802
|
+
# table object
|
803
|
+
table = Text::Table.new
|
804
|
+
|
805
|
+
# get array of keys
|
806
|
+
keys = hsh.keys
|
807
|
+
|
808
|
+
# sort if necessary
|
809
|
+
if opts['sort']
|
810
|
+
keys.sort!{|a,b| a.to_s.downcase <=> b.to_s.downcase}
|
811
|
+
end
|
812
|
+
|
813
|
+
# loop through keys
|
814
|
+
keys.each do |k|
|
815
|
+
# get value
|
816
|
+
val = hsh[k]
|
817
|
+
|
818
|
+
# if val is a hash, show a list of hash keys
|
819
|
+
if val.is_a?(Hash)
|
820
|
+
val = val.keys.sort{|a,b| a.to_s <=> b.to_s}
|
821
|
+
val = val.map{|vk| vk.to_s}
|
822
|
+
val = '{' + val.join(', ') + '}'
|
823
|
+
|
824
|
+
# if array, join elements
|
825
|
+
elsif val.is_a?(Array)
|
826
|
+
val = val.map{|vk| vk.to_s}
|
827
|
+
val = '[' + val.join(' | ') + ']'
|
828
|
+
|
829
|
+
# trim value display
|
830
|
+
else
|
831
|
+
# val = val.to_s
|
832
|
+
val = TTM.object_display_string(val)
|
833
|
+
|
834
|
+
if val.length > 120
|
835
|
+
val = val[0..117] + '...'
|
836
|
+
end
|
837
|
+
end
|
838
|
+
|
839
|
+
# add to table
|
840
|
+
table.rows.push [k, val]
|
841
|
+
end
|
842
|
+
|
843
|
+
# output
|
844
|
+
TTM.puts table.to_s
|
845
|
+
end
|
846
|
+
end
|
847
|
+
#
|
848
|
+
# show_hash
|
849
|
+
#---------------------------------------------------------------------------
|
850
|
+
end
|
851
|
+
#
|
852
|
+
# TTM::Show
|
853
|
+
#===============================================================================
|
854
|
+
|
855
|
+
|
856
|
+
#===============================================================================
|
857
|
+
# TTM::Memory
|
858
|
+
#
|
859
|
+
class TTM::Memory
|
860
|
+
# Returns the array used to store output strings. You probably don't need
|
861
|
+
# this method for anything; it's just handy for debugging.
|
862
|
+
# @return [Array]
|
863
|
+
attr_reader :str
|
864
|
+
|
865
|
+
# Initializes the Memory object. Doesn't actually do anything with the
|
866
|
+
# p_path param, but sending that param is the standard for any class that
|
867
|
+
# can be used with TTM.io.
|
868
|
+
def initialize(p_path)
|
869
|
+
clear()
|
870
|
+
end
|
871
|
+
|
872
|
+
# Adds a string to @strs.
|
873
|
+
# @param [String] str
|
874
|
+
def puts(str)
|
875
|
+
@str += str + "\n"
|
876
|
+
end
|
877
|
+
|
878
|
+
# Returns the string that is stored in memory.
|
879
|
+
# @return [String]
|
880
|
+
def to_s
|
881
|
+
return @str
|
882
|
+
end
|
883
|
+
|
884
|
+
# Resets @str to an empty string.
|
885
|
+
def clear
|
886
|
+
@str = ''
|
887
|
+
end
|
888
|
+
end
|
889
|
+
#
|
890
|
+
# TTM::Memory
|
891
|
+
#===============================================================================
|
892
|
+
|
893
|
+
|
894
|
+
#===============================================================================
|
895
|
+
# TTM::File
|
896
|
+
#
|
897
|
+
|
898
|
+
# Outputs to a file.
|
899
|
+
|
900
|
+
class TTM::File
|
901
|
+
# The path to the file.
|
902
|
+
# @return [String]
|
903
|
+
attr_reader :path
|
904
|
+
|
905
|
+
# Initializes the object. Stores p_path into @path.
|
906
|
+
# @param [String] p_path
|
907
|
+
def initialize(p_path)
|
908
|
+
@path = p_path
|
909
|
+
end
|
910
|
+
|
911
|
+
# Outputs the given string to the file. Every call to #puts opens the file,
|
912
|
+
# locks it, and appends the string to the end of the file.
|
913
|
+
# @param [String] str
|
914
|
+
# @return [Nil]
|
915
|
+
def puts(str)
|
916
|
+
File.open(@path, 'a+') do |file_io|
|
917
|
+
file_io.flock File::LOCK_EX
|
918
|
+
file_io.seek 0, IO::SEEK_END
|
919
|
+
|
920
|
+
begin
|
921
|
+
file_io.puts str
|
922
|
+
ensure
|
923
|
+
file_io.flock File::LOCK_UN
|
924
|
+
end
|
925
|
+
end
|
926
|
+
end
|
927
|
+
|
928
|
+
# Reads the file and returns its content. If the file doesn't exist then an
|
929
|
+
# empty string is returned.
|
930
|
+
# @return [String]
|
931
|
+
def to_s
|
932
|
+
if File.exist?(@path)
|
933
|
+
return File.read(@path)
|
934
|
+
else
|
935
|
+
return ''
|
936
|
+
end
|
937
|
+
end
|
938
|
+
|
939
|
+
# Deletes the ouput file.
|
940
|
+
# @return [Nil]
|
941
|
+
def clear
|
942
|
+
begin
|
943
|
+
File.delete @path
|
944
|
+
rescue
|
945
|
+
end
|
946
|
+
|
947
|
+
return nil
|
948
|
+
end
|
949
|
+
end
|
950
|
+
#
|
951
|
+
# TTM::File
|
952
|
+
#===============================================================================
|
metadata
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: tatum
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: '1.0'
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Mike O'Sullivan
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2023-05-18 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: text-table
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.2'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.2'
|
27
|
+
description: Utilities for outputting information to the user
|
28
|
+
email: mike@idocs.com
|
29
|
+
executables: []
|
30
|
+
extensions: []
|
31
|
+
extra_rdoc_files: []
|
32
|
+
files:
|
33
|
+
- README.md
|
34
|
+
- lib/tatum.rb
|
35
|
+
homepage: https://github.com/mikosullivan/tatum
|
36
|
+
licenses:
|
37
|
+
- MIT
|
38
|
+
metadata: {}
|
39
|
+
post_install_message:
|
40
|
+
rdoc_options: []
|
41
|
+
require_paths:
|
42
|
+
- lib
|
43
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
49
|
+
requirements:
|
50
|
+
- - ">="
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: '0'
|
53
|
+
requirements: []
|
54
|
+
rubygems_version: 3.1.2
|
55
|
+
signing_key:
|
56
|
+
specification_version: 4
|
57
|
+
summary: Tatum
|
58
|
+
test_files: []
|