tatum 1.0

Sign up to get free protection for your applications and to get access to all the features.
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: []