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.
Files changed (4) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +59 -0
  3. data/lib/tatum.rb +952 -0
  4. 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: []