utils 0.68.0 → 0.69.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 (56) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +251 -18
  3. data/bin/ascii7 +28 -0
  4. data/bin/blameline +17 -0
  5. data/bin/changes +69 -5
  6. data/bin/classify +128 -7
  7. data/bin/code_comment +102 -104
  8. data/bin/commit_message +26 -2
  9. data/bin/create_cstags +18 -0
  10. data/bin/create_tags +10 -0
  11. data/bin/discover +38 -1
  12. data/bin/edit +14 -1
  13. data/bin/edit_wait +14 -0
  14. data/bin/enum +139 -15
  15. data/bin/git-empty +50 -0
  16. data/bin/git-versions +20 -0
  17. data/bin/json_check +15 -1
  18. data/bin/long_lines +11 -2
  19. data/bin/myex +38 -0
  20. data/bin/on_change +22 -0
  21. data/bin/path +21 -0
  22. data/bin/print_method +29 -1
  23. data/bin/probe +52 -4
  24. data/bin/rainbow +52 -0
  25. data/bin/rd2md +15 -0
  26. data/bin/search +83 -1
  27. data/bin/sedit +6 -0
  28. data/bin/serve +18 -3
  29. data/bin/ssh-tunnel +14 -2
  30. data/bin/strip_spaces +17 -9
  31. data/bin/sync_dir +48 -1
  32. data/bin/untest +19 -1
  33. data/bin/utils-utilsrc +42 -6
  34. data/bin/vcf2alias +33 -0
  35. data/bin/yaml_check +24 -2
  36. data/lib/utils/config_dir.rb +127 -0
  37. data/lib/utils/config_file.rb +445 -1
  38. data/lib/utils/editor.rb +215 -3
  39. data/lib/utils/finder.rb +127 -16
  40. data/lib/utils/grepper.rb +90 -1
  41. data/lib/utils/irb.rb +387 -39
  42. data/lib/utils/line_blamer.rb +28 -0
  43. data/lib/utils/line_formatter.rb +198 -0
  44. data/lib/utils/md5.rb +14 -0
  45. data/lib/utils/patterns.rb +77 -3
  46. data/lib/utils/probe_server.rb +302 -23
  47. data/lib/utils/ssh_tunnel_specification.rb +58 -0
  48. data/lib/utils/version.rb +1 -1
  49. data/lib/utils/xt/source_location_extension.rb +18 -6
  50. data/lib/utils.rb +3 -1
  51. data/tests/utils_test.rb +7 -1
  52. data/utils.gemspec +5 -5
  53. metadata +4 -6
  54. data/bin/number_files +0 -26
  55. data/lib/utils/xdg_config.rb +0 -10
  56. /data/{COPYING → LICENSE} +0 -0
data/lib/utils/irb.rb CHANGED
@@ -1,10 +1,9 @@
1
- require 'tins/xt'
2
1
  require 'irb/completion'
3
2
  require 'enumerator'
4
3
  require 'tempfile'
5
4
  require 'pp'
6
- require_maybe 'ap'
7
5
  require 'utils'
6
+ require_maybe 'ap'
8
7
 
9
8
  $editor = Utils::Editor.new
10
9
  $pager = ENV['PAGER'] || 'less -r'
@@ -16,6 +15,14 @@ module Utils
16
15
  include FileUtils
17
16
  include Tins::Find
18
17
 
18
+ # The receiver_unless_main method retrieves the receiver name of a method
19
+ # unless it is the main object, optionally executing a block with the
20
+ # receiver name.
21
+ #
22
+ # @param method [ Method ] the method object to inspect
23
+ # @param block [ Proc ] an optional block to execute with the receiver name
24
+ #
25
+ # @return [ String, nil ] the receiver name if it is not 'main', otherwise nil
19
26
  def receiver_unless_main(method, &block)
20
27
  receiver_name = method.receiver.to_s
21
28
  if receiver_name != 'main'
@@ -28,8 +35,16 @@ module Utils
28
35
  end
29
36
  private :receiver_unless_main
30
37
 
31
- # Start _ri_ for +pattern+. If +pattern+ is not string like, call it with
32
- # pattern.class.name as argument.
38
+ # The ri method invokes the ri documentation tool to display help
39
+ # information for the specified patterns. It automatically determines the
40
+ # pattern to search for when none are provided.
41
+ # The method handles different types of patterns including modules,
42
+ # objects that respond to to_str, and other objects. Documentation is
43
+ # displayed through the system's ri command with output piped to the
44
+ # pager.
45
+ #
46
+ # @param patterns [ Array ] the patterns to search for in the documentation
47
+ # @param doc [ String ] the documentation command to execute (defaults to 'ri')
33
48
  def ri(*patterns, doc: 'ri')
34
49
  patterns.empty? and
35
50
  receiver_unless_main(method(__method__)) do |pattern|
@@ -48,10 +63,25 @@ module Utils
48
63
  system "#{doc} #{patterns.map { |p| "'#{p}'" } * ' ' } | #$pager"
49
64
  end
50
65
 
66
+ # The yri method invokes the ri documentation tool with yri as the
67
+ # documenter to display help information for the specified patterns.
68
+ #
69
+ # @param patterns [ Array<String> ] the patterns to look up documentation for
51
70
  def yri(*patterns)
52
71
  ri(*patterns, doc: 'yri')
53
72
  end
54
73
 
74
+ # The irb_open method opens a URL or executes a block to capture output
75
+ # and open it.
76
+ #
77
+ # This method provides a way to open URLs or capture the output of a
78
+ # block and open it in the default application. If a URL is provided, it
79
+ # directly opens the URL. If a block is given, it captures the output of
80
+ # the block, writes it to a temporary file, and opens that file. If
81
+ # neither is provided, it raises an error.
82
+ #
83
+ # @param url [ String, nil ] the URL to open
84
+ # @param block [ Proc, nil ] the block to capture output from
55
85
  def irb_open(url = nil, &block)
56
86
  case
57
87
  when url
@@ -69,22 +99,42 @@ module Utils
69
99
  end
70
100
  end
71
101
 
72
- # TODO: change the API of this stuff
73
-
74
- # Return all instance methods of obj's class.
102
+ # This method obtains the complete list of instance methods available for
103
+ # the specified object's class, then processes them through the
104
+ # irb_wrap_methods helper to prepare them for interactive use in IRB.
105
+ #
106
+ # @param obj [ Object ] the object whose class instance methods are to be retrieved
107
+ #
108
+ # @return [ Array ] an array of wrapped method objects suitable for IRB interaction
75
109
  def irb_all_class_instance_methods(obj = self)
76
110
  methods = obj.class.instance_methods
77
111
  irb_wrap_methods obj, methods
78
112
  end
79
113
 
80
- # Return instance methods of obj's class without the inherited/mixed in
81
- # methods.
114
+ # The irb_class_instance_methods method retrieves instance methods
115
+ # defined directly in the class of the given object, excluding inherited
116
+ # methods, and wraps them for enhanced interactive exploration in IRB
117
+ # environment.
118
+ #
119
+ # @param obj [ Object ] the object whose class instance methods are to be retrieved
120
+ #
121
+ # @return [ Array ] an array of wrapped method objects suitable for IRB interaction
82
122
  def irb_class_instance_methods(obj = self)
83
123
  methods = obj.class.instance_methods(false)
84
124
  irb_wrap_methods obj, methods
85
125
  end
86
126
 
87
- # Return all instance methods defined in module modul.
127
+ # The irb_all_instance_methods method retrieves all instance methods
128
+ # defined on a module.
129
+ #
130
+ # This method collects the instance methods from the specified module and
131
+ # wraps them for enhanced interactive exploration in IRB. It is designed
132
+ # to provide a more user-friendly interface for examining module methods
133
+ # within the interactive Ruby environment.
134
+ #
135
+ # @param modul [ Object ] the module from which to retrieve instance methods
136
+ #
137
+ # @return [ Array ] an array of wrapped method objects suitable for IRB interaction
88
138
  def irb_all_instance_methods(modul = self)
89
139
  methods = modul.instance_methods
90
140
  irb_wrap_methods modul, methods, true
@@ -92,19 +142,48 @@ module Utils
92
142
 
93
143
  # Return instance methods defined in module modul without the inherited/mixed
94
144
  # in methods.
145
+ # The irb_instance_methods method retrieves instance methods defined directly in a module.
146
+ #
147
+ # This method fetches all instance methods that are explicitly defined within the specified module,
148
+ # excluding inherited methods. It then wraps these methods for enhanced interactive exploration
149
+ # within the IRB environment.
150
+ #
151
+ # @param modul [ Object ] the module from which to retrieve instance methods
152
+ #
153
+ # @return [ Array ] an array of wrapped method objects suitable for IRB interaction
95
154
  def irb_instance_methods(modul = self)
96
155
  methods = modul.instance_methods(false)
97
156
  irb_wrap_methods modul, methods, true
98
157
  end
99
158
 
100
- # Return all methods of obj (including obj's eigenmethods.)
159
+ # The irb_all_methods method retrieves all methods available on an
160
+ # object.
161
+ #
162
+ # This method collects all methods associated with the given object
163
+ # (including its singleton methods) and wraps them for enhanced
164
+ # interactive exploration in IRB. It provides a comprehensive list
165
+ # of methods that can be used to understand the object's capabilities and
166
+ # interface.
167
+ #
168
+ # @param obj [ Object ] the object whose methods are to be retrieved
169
+ #
170
+ # @return [ Array ] an array of wrapped method objects for interactive use
101
171
  def irb_all_methods(obj = self)
102
172
  methods = obj.methods
103
173
  irb_wrap_methods obj, methods
104
174
  end
105
175
 
106
- # Return instance methods of obj's class without the inherited/mixed in
107
- # methods, but including obj's eigenmethods.
176
+ # The irb_methods method retrieves instance methods defined in the class
177
+ # hierarchy excluding those inherited from ancestor classes.
178
+ #
179
+ # This method computes a list of instance methods that are directly
180
+ # defined in the class of the given object, excluding any methods that
181
+ # are inherited from its superclass or modules. It then wraps these
182
+ # methods for enhanced display in IRB.
183
+ #
184
+ # @param obj [ Object ] the object whose class methods are to be examined
185
+ #
186
+ # @return [ Array ] an array of wrapped method objects for display in IRB
108
187
  def irb_methods(obj = self)
109
188
  methods = obj.class.ancestors[1..-1].inject(obj.methods) do |all, a|
110
189
  all -= a.instance_methods
@@ -112,11 +191,32 @@ module Utils
112
191
  irb_wrap_methods obj, methods
113
192
  end
114
193
 
115
- # Return all eigen methods of obj.
116
- def irb_eigen_methods(obj = self)
194
+ # The irb_singleton_methods method retrieves singleton methods associated
195
+ # with an object.
196
+ #
197
+ # This method collects all singleton methods defined on the specified object,
198
+ # excluding inherited methods, and prepares them for display in an interactive
199
+ # Ruby environment.
200
+ #
201
+ # @param obj [ Object ] the object whose singleton methods are to be retrieved
202
+ #
203
+ # @return [ Array ] an array of singleton method names associated with the object
204
+ def irb_singleton_methods(obj = self)
117
205
  irb_wrap_methods obj, obj.methods(false)
118
206
  end
119
207
 
208
+ # The irb_wrap_methods method creates wrapped method objects for introspection.
209
+ #
210
+ # This method takes a set of method names and wraps them in a way that allows
211
+ # for easier inspection and display within an IRB session. It handles
212
+ # potential errors during the wrapping process by rescuing exceptions and
213
+ # filtering out invalid entries.
214
+ #
215
+ # @param obj [ Object ] the object whose methods are being wrapped
216
+ # @param methods [ Array ] the array of method names to wrap
217
+ # @param modul [ TrueClass, FalseClass ] flag indicating if the methods are module methods
218
+ #
219
+ # @return [ Array ] an array of wrapped method objects sorted in ascending order
120
220
  def irb_wrap_methods(obj = self, methods = methods(), modul = false)
121
221
  methods.map do |name|
122
222
  MethodWrapper.new(obj, name, modul) rescue nil
@@ -126,6 +226,14 @@ module Utils
126
226
  class WrapperBase
127
227
  include Comparable
128
228
 
229
+ # The initialize method sets up the instance name by converting the
230
+ # input to a string representation.
231
+ #
232
+ # This method handles different input types by converting them to a
233
+ # string, prioritizing to_str over to_sym and falling back to to_s if
234
+ # neither is available.
235
+ #
236
+ # @param name [ Object ] the input name to be converted to a string
129
237
  def initialize(name)
130
238
  @name =
131
239
  case
@@ -138,8 +246,16 @@ module Utils
138
246
  end
139
247
  end
140
248
 
249
+ # The name reader method returns the value of the name instance
250
+ # variable.
251
+ #
252
+ # @return [ String] the value stored in the name instance variable
141
253
  attr_reader :name
142
254
 
255
+ # The description reader method provides access to the description
256
+ # attribute.
257
+ #
258
+ # @return [ String, nil ] the description value or nil if not set
143
259
  attr_reader :description
144
260
 
145
261
  alias to_str description
@@ -148,63 +264,148 @@ module Utils
148
264
 
149
265
  alias to_s description
150
266
 
267
+ # The == method assigns a new name value to the instance variable.
268
+ #
269
+ # @param name [ Object ] the name value to be assigned
270
+ #
271
+ # @return [ Object ] returns the assigned name value
151
272
  def ==(name)
152
273
  @name = name
153
274
  end
154
275
 
155
276
  alias eql? ==
156
277
 
278
+ # The hash method returns the hash value of the name attribute.
279
+ #
280
+ # @return [ Integer ] the hash value used for object identification
157
281
  def hash
158
282
  @name.hash
159
283
  end
160
284
 
285
+ # The <=> method compares the names of two objects for sorting purposes.
286
+ #
287
+ # @param other [ Object ] the other object to compare against
288
+ #
289
+ # @return [ Integer ] -1 if this object's name is less than the other's,
290
+ # 0 if they are equal, or 1 if this object's name is greater than the other's
161
291
  def <=>(other)
162
292
  @name <=> other.name
163
293
  end
164
294
  end
165
295
 
166
296
  class MethodWrapper < WrapperBase
297
+ # The initialize method sets up a new instance with the specified
298
+ # object, method name, and module flag.
299
+ #
300
+ # This method creates and configures a new instance by storing the
301
+ # method object and its description, handling both instance methods and
302
+ # regular methods based on the module flag parameter.
303
+ #
304
+ # @param obj [ Object ] the object from which to retrieve the method
305
+ # @param name [ String ] the name of the method to retrieve
306
+ # @param modul [ TrueClass, FalseClass ] flag indicating whether to retrieve an instance method
167
307
  def initialize(obj, name, modul)
168
308
  super(name)
169
309
  @method = modul ? obj.instance_method(name) : obj.method(name)
170
310
  @description = @method.description(style: :namespace)
171
311
  end
172
312
 
313
+ # The method reader returns the method object associated with the
314
+ # instance.
173
315
  attr_reader :method
174
316
 
317
+ # The owner method retrieves the owner of the method object.
318
+ #
319
+ # This method checks if the wrapped method object responds to the owner
320
+ # message and returns the owner if available, otherwise it returns nil.
321
+ #
322
+ # @return [ Object, nil ] the owner of the method or nil if not applicable
175
323
  def owner
176
324
  method.respond_to?(:owner) ? method.owner : nil
177
325
  end
178
326
 
327
+ # The arity method returns the number of parameters expected by the method.
328
+ #
329
+ # @return [ Integer ] the number of required parameters for the method
179
330
  def arity
180
331
  method.arity
181
332
  end
182
333
 
334
+ # The source_location method retrieves the file path and line number
335
+ # where the method is defined.
336
+ #
337
+ # This method accesses the underlying source location information for
338
+ # the method object, returning an array that contains the filename and
339
+ # line number of the method's definition.
340
+ #
341
+ # @return [ Array<String, Integer> ] an array containing the filename and line number
342
+ # where the method is defined, or nil if the location cannot be determined
183
343
  def source_location
184
344
  method.source_location
185
345
  end
186
346
 
347
+ # The <=> method compares the descriptions of two objects for ordering
348
+ # purposes.
349
+ #
350
+ # @param other [ Object ] the other object to compare against
351
+ #
352
+ # @return [ Integer ] -1 if this object's description is less than the other's,
353
+ # 0 if they are equal, or 1 if this object's description is greater than the other's
187
354
  def <=>(other)
188
355
  @description <=> other.description
189
356
  end
190
357
  end
191
358
 
192
359
  class ConstantWrapper < WrapperBase
360
+ # The initialize method sets up a new instance with the provided object
361
+ # and name.
362
+ #
363
+ # This method configures the instance by storing a reference to the
364
+ # object's class and creating a description string that combines the
365
+ # name with the class name.
366
+ #
367
+ # @param obj [ Object ] the object whose class will be referenced
368
+ # @param name [ String ] the name to be used in the description
369
+ #
370
+ # @return [ Utils::Patterns::Pattern ] a new pattern instance configured with the provided arguments
193
371
  def initialize(obj, name)
194
372
  super(name)
195
373
  @klass = obj.class
196
374
  @description = "#@name:#@klass"
197
375
  end
198
376
 
377
+ # The klass reader method provides access to the class value stored in the instance.
378
+ #
379
+ # @return [ Object ] the class value
199
380
  attr_reader :klass
200
381
  end
201
382
 
202
- # Return all the constants defined in +modul+.
383
+ # The irb_constants method retrieves and wraps all constants from a given
384
+ # module.
385
+ #
386
+ # This method collects all constants defined in the specified module,
387
+ # creates ConstantWrapper instances for each constant, and returns them
388
+ # sorted in ascending order.
389
+ #
390
+ # @param modul [ Object ] the module from which to retrieve constants
391
+ #
392
+ # @return [ Array<ConstantWrapper> ] an array of ConstantWrapper objects
393
+ # representing the constants in the module, sorted alphabetically
203
394
  def irb_constants(modul = self)
204
395
  modul.constants.map { |c| ConstantWrapper.new(modul.const_get(c), c) }.sort
205
396
  end
206
397
 
207
- # Return all the subclasses of +klass+. TODO implement subclasses w/out rails
398
+ # The irb_subclasses method retrieves and wraps subclass information for
399
+ # a given class.
400
+ #
401
+ # This method fetches the subclasses of the specified class and creates
402
+ # ConstantWrapper instances for each subclass, allowing them to be sorted
403
+ # and displayed in a structured format.
404
+ #
405
+ # @param klass [ Object ] the class object to retrieve subclasses from
406
+ #
407
+ # @return [ Array<ConstantWrapper> ] an array of ConstantWrapper objects
408
+ # representing the subclasses
208
409
  def irb_subclasses(klass = self)
209
410
  klass.subclasses.map { |c| ConstantWrapper.new(eval(c), c) }.sort
210
411
  end
@@ -213,6 +414,18 @@ module Utils
213
414
  Infinity = 1.0 / 0 # I like to define the infinite.
214
415
  end
215
416
 
417
+ # The capture_output method captures stdout and optionally stderr output
418
+ # during code execution.
419
+ #
420
+ # This method temporarily redirects standard output (and optionally
421
+ # standard error) to a temporary file, executes the provided block, and
422
+ # then returns the captured output as a string.
423
+ #
424
+ # @param with_stderr [ TrueClass, FalseClass ] whether to also capture standard error output
425
+ #
426
+ # @yield [ void ] the block of code to execute while capturing output
427
+ #
428
+ # @return [ String ] the captured output as a string
216
429
  def capture_output(with_stderr = false)
217
430
  require 'tempfile'
218
431
  begin
@@ -229,11 +442,16 @@ module Utils
229
442
  temp.read
230
443
  end
231
444
 
232
- def le(with_stderr = false, &block)
233
- less(with_stderr) { block.call(self) }
234
- end
235
-
236
- # Use pager on the output of the commands given in the block.
445
+ # Use pager on the output of the commands given in the block. The less
446
+ # method executes a block and outputs its result through the pager.
447
+ #
448
+ # This method runs the provided block in a controlled environment,
449
+ # captures its output, and streams that output through the system's
450
+ # configured pager for display.
451
+ #
452
+ # @param with_stderr [ TrueClass, FalseClass ] whether to include standard error in the capture
453
+ #
454
+ # @yield [ void ]
237
455
  def less(with_stderr = false, &block)
238
456
  IO.popen($pager, 'w') do |f|
239
457
  f.write capture_output(with_stderr, &block)
@@ -242,35 +460,67 @@ module Utils
242
460
  nil
243
461
  end
244
462
 
245
- def irb_time(n = 1)
463
+ # The irb_time method measures the execution time of a block and outputs
464
+ # the duration to standard error.
465
+ #
466
+ # @param n [ Integer ] the number of times to execute the block, defaults
467
+ # to 1
468
+ #
469
+ # @yield [ block ] the block to be executed and timed
470
+ def irb_time(n = 1, &block)
246
471
  s = Time.now
247
- n.times do
248
- yield
249
- end
472
+ n.times(&block)
250
473
  d = Time.now - s
474
+ ensure
475
+ d ||= Time.now - s
251
476
  if n == 1
252
477
  warn "Took %.3fs seconds." % d
253
478
  else
254
479
  warn "Took %.3fs seconds, %.3fs per call (avg)." % [ d, d / n ]
255
480
  end
256
- d
257
481
  end
258
482
 
259
- def irb_time_tap(n = 1)
483
+ # The irb_time_result method executes a block n times while measuring
484
+ # execution time and returns the result of the last execution.
485
+ #
486
+ # @param n [ Integer ] the number of times to execute the block
487
+ #
488
+ # @yield [ i ]
489
+ #
490
+ # @return [ Object ] the result of the last block execution
491
+ def irb_time_result(n = 1)
260
492
  r = nil
261
- irb_time(n) { r = yield }
493
+ irb_time(n) { |i| r = yield(i) }
262
494
  r
263
495
  end
264
496
 
497
+ # The irb_time_watch method monitors and reports performance metrics over
498
+ # time.
499
+ #
500
+ # This method continuously measures the output of a provided block,
501
+ # calculating differences and rates of change between successive
502
+ # measurements. It tracks these metrics and displays them with timing
503
+ # information, useful for observing how values evolve during execution.
504
+ #
505
+ # @param duration [ Integer ] the time interval in seconds between
506
+ # measurements
507
+ #
508
+ # @yield [ i ] the block to be measured, receiving the iteration count as an argument
265
509
  def irb_time_watch(duration = 1)
266
510
  start = Time.now
267
511
  pre = nil
268
512
  avg = Hash.new
513
+ i = 0
514
+ fetch_next = -> cur do
515
+ pre = cur.map(&:to_f)
516
+ i += 1
517
+ sleep duration
518
+ end
269
519
  loop do
270
- cur = [ yield ].flatten
520
+ cur = [ yield(i) ].flatten
271
521
  unless pre
272
- pre = cur.map(&:to_f)
273
- cur = [ yield ].flatten
522
+ fetch_next.(cur)
523
+ redo
274
524
  end
275
525
  expired = Time.now - start
276
526
  diffs = cur.zip(pre).map { |c, p| c - p }
@@ -288,12 +538,25 @@ module Utils
288
538
  end
289
539
  avg[i]
290
540
  }
291
- warn "#{expired} #{cur.zip(diffs, rates, durs).map(&:inspect) * ' '} 𝝙 / per sec."
292
- pre = cur.map(&:to_f)
541
+ warn "#{expired} #{cur.zip(diffs, rates, durs) * ' '} 𝝙 / per sec."
542
+ fetch_next.(cur)
293
543
  sleep duration
294
544
  end
295
545
  end
296
546
 
547
+ # The irb_write method writes text to a file or executes a block to
548
+ # generate content for writing.
549
+ #
550
+ # This method provides a convenient way to write content to a file,
551
+ # either by passing the text directly or by executing a block that
552
+ # generates the content. It uses secure file writing to ensure safety.
553
+ #
554
+ # @param filename [ String ] the path to the file where content will be
555
+ # written
556
+ # @param text [ String, nil ] the text content to write to the file, or
557
+ # nil if using a block
558
+ #
559
+ # @yield [ ] a block that generates content to be written to the file
297
560
  def irb_write(filename, text = nil, &block)
298
561
  if text.nil? && block
299
562
  File.secure_write filename, nil, 'wb', &block
@@ -302,6 +565,21 @@ module Utils
302
565
  end
303
566
  end
304
567
 
568
+ # The irb_read method reads the contents of a file either entirely or in
569
+ # chunks. When a block is provided, it reads the file in chunks of the
570
+ # specified size and yields each chunk to the block.
571
+ # If no block is given, it reads the entire file content at once and
572
+ # returns it as a string.
573
+ #
574
+ # @param filename [ String ] the path to the file to be read
575
+ # @param chunk_size [ Integer ] the size of each chunk to read when a
576
+ # block is provided
577
+ #
578
+ # @yield [ chunk ] yields each chunk of the file to the block
579
+ # @yieldparam chunk [ String ] a portion of the file content
580
+ #
581
+ # @return [ String, nil ] the entire file content if no block is given,
582
+ # otherwise nil
305
583
  def irb_read(filename, chunk_size = 8_192)
306
584
  if block_given?
307
585
  File.open(filename) do |file|
@@ -309,11 +587,25 @@ module Utils
309
587
  yield file.read(chunk_size)
310
588
  end
311
589
  end
590
+ nil
312
591
  else
313
592
  File.read filename
314
593
  end
315
594
  end
316
595
 
596
+ # The irb_load! method loads Ruby files by their names into the current
597
+ # environment.
598
+ #
599
+ # This method takes one or more file names and attempts to locate and
600
+ # load the corresponding Ruby files from the current directory and its
601
+ # subdirectories. It ensures that each file is loaded only once by
602
+ # tracking loaded files using their MD5 checksums. The method outputs
603
+ # messages to standard error indicating which files have been
604
+ # successfully loaded.
605
+ #
606
+ # @param files [ Array<String> ] the names of the Ruby files to be loaded
607
+ #
608
+ # @return [ nil ] always returns nil after processing all specified files
317
609
  def irb_load!(*files)
318
610
  files = files.map { |f| f.gsub(/(\.rb)?\Z/, '.rb') }
319
611
  loaded = {}
@@ -333,6 +625,14 @@ module Utils
333
625
  nil
334
626
  end
335
627
 
628
+ # The ed method opens files for editing using the system editor.
629
+ #
630
+ # This method provides a convenient way to edit files by invoking the
631
+ # configured editor. When called without arguments, it edits the current
632
+ # object's representation. When called with file arguments, it edits those
633
+ # specific files.
634
+ #
635
+ # @param files [ Array ] an array of file paths to be edited
336
636
  def ed(*files)
337
637
  if files.empty?
338
638
  $editor.full?(:edit, self)
@@ -343,6 +643,16 @@ module Utils
343
643
 
344
644
  if defined?(ActiveRecord::Base)
345
645
  $logger = Logger.new(STDERR)
646
+ # The irb_toggle_logging method toggles the logging configuration for
647
+ # ActiveRecord.
648
+ #
649
+ # This method manages the logger setting for ActiveRecord by switching
650
+ # between a custom logger and the previously configured logger. It
651
+ # returns true when switching to the custom logger, and false when
652
+ # reverting to the original logger.
653
+ #
654
+ # @return [ TrueClass, FalseClass ] true if the logger was switched to
655
+ # the custom logger, false if it was reverted to the original logger
346
656
  def irb_toggle_logging
347
657
  require 'logger'
348
658
  if ActiveRecord::Base.logger != $logger
@@ -358,14 +668,39 @@ module Utils
358
668
  end
359
669
 
360
670
  module Regexp
361
- # Show the match of this Regexp on the +string+.
362
- def show_match(string)
363
- string =~ self ? "#{$`}<<#{$&}>>#{$'}" : "no match"
671
+ # The show_match method evaluates a string against the receiver pattern
672
+ # and highlights matching portions.
673
+ #
674
+ # This method tests whether the provided string matches the pattern
675
+ # represented by the receiver. When a match is found, it applies the
676
+ # success proc to highlight the matched portion of the string. If no
677
+ # match is found, it applies the failure proc to indicate that no match
678
+ # was found.
679
+ #
680
+ # @param string [ String ] the string to be tested against the pattern
681
+ # @param success [ Proc ] a proc that processes the matched portion of the string
682
+ # @param failure [ Proc ] a proc that processes the "no match" indication
683
+ #
684
+ # @return [ String ] the formatted string with matched portions highlighted or a no match message
685
+ def show_match(
686
+ string,
687
+ success: -> s { Term::ANSIColor.green { s } },
688
+ failure: -> s { Term::ANSIColor.red { s } }
689
+ )
690
+ string =~ self ? "#{$`}#{success.($&)}#{$'}" : failure.("no match")
364
691
  end
365
692
  end
366
693
 
367
694
  module String
368
- # Pipe this string into +cmd+.
695
+ # The | method executes a shell command and returns its output.
696
+ #
697
+ # This method takes a command string, pipes the current string to it via
698
+ # stdin, captures the command's stdout, and returns the resulting output
699
+ # as a string.
700
+ #
701
+ # @param cmd [ String ] the shell command to execute
702
+ #
703
+ # @return [ String ] the output of the executed command
369
704
  def |(cmd)
370
705
  IO.popen(cmd, 'w+') do |f|
371
706
  f.write self
@@ -374,12 +709,25 @@ module Utils
374
709
  end
375
710
  end
376
711
 
377
- # Write this string into file +filename+.
712
+ # The >> method writes the string content to a file securely.
713
+ #
714
+ # This method takes a filename and uses File.secure_write to write the
715
+ # string's content to that file, ensuring secure file handling practices
716
+ # are followed.
717
+ #
718
+ # @param filename [ String ] the path to the file where the string content will be written
719
+ #
720
+ # @return [ Integer ] the number of bytes written to the file
378
721
  def >>(filename)
379
722
  File.secure_write(filename, self)
380
723
  end
381
724
  end
382
725
 
726
+ # The configure method sets up IRB configuration options.
727
+ #
728
+ # This method configures the IRB environment by setting the history save
729
+ # limit and customizing the prompt display when IRB is running in
730
+ # interactive mode.
383
731
  def self.configure
384
732
  ::IRB.conf[:SAVE_HISTORY] = 1000
385
733
  if ::IRB.conf[:PROMPT]