tins 1.43.0 → 1.44.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 (105) hide show
  1. checksums.yaml +4 -4
  2. data/.contexts/code_comment.rb +5 -8
  3. data/.contexts/lib.rb +0 -2
  4. data/CHANGES.md +12 -0
  5. data/README.md +158 -6
  6. data/Rakefile +19 -16
  7. data/examples/let.rb +8 -40
  8. data/examples/mail.rb +0 -1
  9. data/examples/turing.rb +3 -1
  10. data/lib/tins/alias.rb +1 -0
  11. data/lib/tins/annotate.rb +37 -27
  12. data/lib/tins/ask_and_send.rb +41 -0
  13. data/lib/tins/attempt.rb +39 -0
  14. data/lib/tins/bijection.rb +34 -0
  15. data/lib/tins/case_predicate.rb +21 -0
  16. data/lib/tins/complete.rb +16 -0
  17. data/lib/tins/concern.rb +64 -0
  18. data/lib/tins/date_dummy.rb +36 -4
  19. data/lib/tins/date_time_dummy.rb +34 -2
  20. data/lib/tins/deep_dup.rb +9 -2
  21. data/lib/tins/deprecate.rb +12 -0
  22. data/lib/tins/dslkit.rb +559 -83
  23. data/lib/tins/duration.rb +120 -5
  24. data/lib/tins/expose.rb +54 -5
  25. data/lib/tins/extract_last_argument_options.rb +9 -0
  26. data/lib/tins/file_binary.rb +104 -21
  27. data/lib/tins/find.rb +114 -11
  28. data/lib/tins/generator.rb +10 -2
  29. data/lib/tins/go.rb +81 -4
  30. data/lib/tins/hash_bfs.rb +4 -2
  31. data/lib/tins/hash_symbolize_keys_recursive.rb +62 -4
  32. data/lib/tins/hash_union.rb +47 -2
  33. data/lib/tins/if_predicate.rb +31 -0
  34. data/lib/tins/implement.rb +50 -0
  35. data/lib/tins/limited.rb +54 -5
  36. data/lib/tins/lines_file.rb +81 -2
  37. data/lib/tins/lru_cache.rb +54 -17
  38. data/lib/tins/memoize.rb +86 -58
  39. data/lib/tins/method_description.rb +87 -4
  40. data/lib/tins/minimize.rb +39 -11
  41. data/lib/tins/module_group.rb +27 -2
  42. data/lib/tins/named_set.rb +20 -0
  43. data/lib/tins/null.rb +86 -15
  44. data/lib/tins/once.rb +61 -4
  45. data/lib/tins/p.rb +44 -8
  46. data/lib/tins/partial_application.rb +66 -7
  47. data/lib/tins/proc_compose.rb +58 -1
  48. data/lib/tins/proc_prelude.rb +97 -10
  49. data/lib/tins/range_plus.rb +30 -2
  50. data/lib/tins/require_maybe.rb +36 -0
  51. data/lib/tins/responding.rb +39 -0
  52. data/lib/tins/secure_write.rb +24 -4
  53. data/lib/tins/sexy_singleton.rb +45 -48
  54. data/lib/tins/string_byte_order_mark.rb +33 -2
  55. data/lib/tins/string_camelize.rb +31 -2
  56. data/lib/tins/string_underscore.rb +33 -2
  57. data/lib/tins/string_version.rb +179 -10
  58. data/lib/tins/subhash.rb +35 -10
  59. data/lib/tins/temp_io.rb +7 -0
  60. data/lib/tins/temp_io_enum.rb +19 -0
  61. data/lib/tins/terminal.rb +31 -9
  62. data/lib/tins/thread_local.rb +67 -5
  63. data/lib/tins/time_dummy.rb +46 -21
  64. data/lib/tins/to.rb +15 -0
  65. data/lib/tins/to_proc.rb +17 -4
  66. data/lib/tins/token.rb +56 -1
  67. data/lib/tins/unit.rb +288 -149
  68. data/lib/tins/version.rb +1 -1
  69. data/lib/tins/write.rb +14 -3
  70. data/lib/tins/xt/blank.rb +81 -2
  71. data/lib/tins/xt/concern.rb +51 -0
  72. data/lib/tins/xt/full.rb +56 -11
  73. data/lib/tins/xt/irb.rb +46 -2
  74. data/lib/tins/xt/method_description.rb +0 -12
  75. data/lib/tins/xt/minimize.rb +7 -0
  76. data/lib/tins/xt/named.rb +71 -16
  77. data/lib/tins/xt/proc_compose.rb +4 -0
  78. data/lib/tins/xt/subhash.rb +11 -0
  79. data/lib/tins/xt/time_freezer.rb +43 -6
  80. data/lib/tins/xt.rb +1 -3
  81. data/lib/tins.rb +16 -3
  82. data/tests/duration_test.rb +4 -0
  83. data/tests/from_module_test.rb +30 -2
  84. data/tests/implement_test.rb +6 -8
  85. data/tests/lines_file_test.rb +2 -0
  86. data/tests/lru_cache_test.rb +12 -0
  87. data/tests/method_description_test.rb +14 -20
  88. data/tests/partial_application_test.rb +4 -0
  89. data/tests/proc_prelude_test.rb +1 -1
  90. data/tests/scope_test.rb +1 -1
  91. data/tests/string_version_test.rb +2 -0
  92. data/tests/to_test.rb +6 -6
  93. data/tins.gemspec +9 -9
  94. metadata +23 -41
  95. data/lib/tins/count_by.rb +0 -21
  96. data/lib/tins/deep_const_get.rb +0 -64
  97. data/lib/tins/timed_cache.rb +0 -51
  98. data/lib/tins/uniq_by.rb +0 -23
  99. data/lib/tins/xt/count_by.rb +0 -7
  100. data/lib/tins/xt/deep_const_get.rb +0 -7
  101. data/lib/tins/xt/uniq_by.rb +0 -25
  102. data/tests/count_by_test.rb +0 -17
  103. data/tests/deep_const_get_test.rb +0 -37
  104. data/tests/uniq_by_test.rb +0 -31
  105. /data/{COPYING → LICENSE} +0 -0
data/lib/tins/duration.rb CHANGED
@@ -1,4 +1,8 @@
1
+ # frozen_string_literal: false
2
+
1
3
  module Tins
4
+ # A class to represent durations with support for formatting and parsing time
5
+ # intervals.
2
6
  class Duration
3
7
  include Comparable
4
8
 
@@ -7,14 +11,37 @@ module Tins
7
11
  #
8
12
  # @param [String] string The duration string to parse.
9
13
  # @param [String] template for the duration format, see {#format}.
14
+ # Default: '%S%d+%h:%m:%s.%f'
10
15
  #
11
16
  # @return [Integer, Float] The number of (fractional) seconds of the duration.
12
17
  #
13
- # @example
18
+ # @raise [ArgumentError] If the string doesn't match the expected template format
19
+ #
20
+ # @example Basic parsing
14
21
  # Tins::Duration.parse('6+05:04:03', template: '%S%d+%h:%m:%s') # => 536643
15
22
  # Tins::Duration.parse('6+05:04:03.21', template: '%S%d+%h:%m:%s.%f') # => 536643.21
23
+ #
24
+ # @example Parsing negative durations
25
+ # Tins::Duration.parse('-6+05:04:03', template: '%S%d+%h:%m:%s') # => -536643
26
+ #
27
+ # @example Custom template parsing
28
+ # Tins::Duration.parse('05:04:03.21', template: '%h:%m:%s.%f') # => 18243.21
29
+ #
30
+ # The parser supports the following directives in templates:
31
+ # - `%S` - Sign indicator (optional negative sign)
32
+ # - `%d` - Days component (integer)
33
+ # - `%h` - Hours component (integer)
34
+ # - `%m` - Minutes component (integer)
35
+ # - `%s` - Seconds component (integer)
36
+ # - `%f` - Fractional seconds component (decimal)
37
+ # - `%%` - Literal percent character
38
+ #
39
+ # The parser is greedy and consumes as much of the input string as possible
40
+ # for each directive.
41
+ # If a directive expects a specific format but doesn't find it, an
42
+ # ArgumentError is raised.
16
43
  def self.parse(string, template: '%S%d+%h:%m:%s.%f')
17
- s, t = string.to_s.dup, template.dup
44
+ s, t = string.to_s.dup, template.dup
18
45
  d, sd = 0, 1
19
46
  loop do
20
47
  t.sub!(/\A(%[Sdhmsf%]|.)/) { |directive|
@@ -44,9 +71,13 @@ module Tins
44
71
  sd * d
45
72
  end
46
73
 
74
+ # Initializes a new Duration object with the specified number of seconds.
75
+ #
76
+ # @param seconds [ Integer, Float ] the total number of seconds to
77
+ # represent
47
78
  def initialize(seconds)
48
- @negative = seconds < 0
49
- seconds = seconds.abs
79
+ @negative = seconds < 0
80
+ seconds = seconds.abs
50
81
  @original_seconds = seconds
51
82
  @days, @hours, @minutes, @seconds, @fractional_seconds =
52
83
  [ 86_400, 3600, 60, 1, 0 ].inject([ [], seconds ]) {|(r, s), d|
@@ -60,40 +91,103 @@ module Tins
60
91
  }
61
92
  end
62
93
 
94
+ # Converts the original seconds value to a floating-point number.
95
+ #
96
+ # @return [Float] the original seconds value as a floating-point number
63
97
  def to_f
64
98
  @original_seconds.to_f
65
99
  end
66
100
 
101
+ # The <=> method compares this object with another object after converting
102
+ # both to floats.
103
+ #
104
+ # @param other [Object] the object to compare with
105
+ #
106
+ # @return [Integer] -1 if this object is less than other, 0 if they are
107
+ # equal, 1 if this object is greater than other
67
108
  def <=>(other)
68
109
  to_f <=> other.to_f
69
110
  end
70
111
 
112
+ # Returns true if the duration is negative.
113
+ #
114
+ # @return [TrueClass, FalseClass] true if the duration represents a
115
+ # negative time interval, false otherwise
71
116
  def negative?
72
117
  @negative
73
118
  end
74
119
 
120
+ # Returns true if the duration includes days, false otherwise.
121
+ #
122
+ # @return [TrueClass, FalseClass] true if the duration has any days, false
123
+ # otherwise
75
124
  def days?
76
125
  @days > 0
77
126
  end
78
127
 
128
+ # Returns true if the duration has any hours component
129
+ #
130
+ # @return [TrueClass, FalseClass] true if hours are present, false
131
+ # otherwise
79
132
  def hours?
80
133
  @hours > 0
81
134
  end
82
135
 
136
+ # Returns true if the duration has minutes, false otherwise.
137
+ #
138
+ # @return [TrueClass, FalseClass] true if minutes are greater than 0, false otherwise
83
139
  def minutes?
84
140
  @minutes > 0
85
141
  end
86
142
 
143
+ # Returns true if the duration has a positive seconds component.
144
+ #
145
+ # @return [TrueClass, FalseClass] true if seconds are greater than zero,
146
+ # false otherwise
87
147
  def seconds?
88
148
  @seconds > 0
89
149
  end
90
150
 
151
+ # Returns true if the duration includes fractional seconds.
152
+ #
153
+ # @return [TrueClass, FalseClass] true if fractional seconds are present,
154
+ # false otherwise
91
155
  def fractional_seconds?
92
156
  @fractional_seconds > 0
93
157
  end
94
158
 
159
+ # Formats the duration according to the given template and precision.
160
+ #
161
+ # The template string supports the following directives:
162
+ # - `%S` - Sign indicator (negative sign if duration is negative)
163
+ # - `%d` - Days component
164
+ # - `%h` - Hours component (zero-padded to 2 digits)
165
+ # - `%m` - Minutes component (zero-padded to 2 digits)
166
+ # - `%s` - Seconds component (zero-padded to 2 digits)
167
+ # - `%f` - Fractional seconds component (without the leading decimal point)
168
+ # - `%D` - Smart format (automatically includes days, fractional seconds, and sign)
169
+ # - `%%` - Literal percent character
170
+ #
171
+ # When using `%f`, the fractional part will be formatted according to the precision parameter.
172
+ #
173
+ # @param template [String] the format template to use for formatting
174
+ # Default: '%S%d+%h:%m:%s.%f'
175
+ # @param precision [Integer] the precision to use for fractional seconds
176
+ # When nil, uses default formatting with 6 decimal places
177
+ #
178
+ # @return [String] the formatted duration string
179
+ #
180
+ # @example Basic formatting
181
+ # duration = Tins::Duration.new(93784.123)
182
+ # duration.format('%d+%h:%m:%s.%f') # => "1+02:03:04.123000"
183
+ #
184
+ # @example Smart format
185
+ # duration.format('%D') # => "1+02:03:04.123"
186
+ #
187
+ # @example Custom precision
188
+ # duration.format('%s.%f', precision: 2) # => "04.12"
95
189
  def format(template = '%S%d+%h:%m:%s.%f', precision: nil)
96
- result = template.gsub(/%[DdhmSs]/) { |directive|
190
+ result = template.gsub(/%[DdhmSs%]/) { |directive|
97
191
  case directive
98
192
  when '%S' then ?- if negative?
99
193
  when '%d' then @days
@@ -101,6 +195,7 @@ module Tins
101
195
  when '%m' then '%02u' % @minutes
102
196
  when '%s' then '%02u' % @seconds
103
197
  when '%D' then format_smart
198
+ when '%%' then '%'
104
199
  end
105
200
  }
106
201
  if result.include?('%f')
@@ -114,12 +209,32 @@ module Tins
114
209
  result
115
210
  end
116
211
 
212
+ # The to_s method returns a string representation of the duration by
213
+ # formatting it using the smart format method
214
+ #
215
+ # @return [String] the formatted duration string
117
216
  def to_s
118
217
  format_smart
119
218
  end
120
219
 
121
220
  private
122
221
 
222
+ # The format_smart method provides intelligent formatting based on the
223
+ # duration's components. It automatically determines which components are
224
+ # present and formats them accordingly, making it ideal for human-readable
225
+ # output where you want to avoid showing zero values.
226
+ #
227
+ # The smart format follows these rules:
228
+ # - If days are present, includes the day component (e.g., "1+02:03:04") -
229
+ # If fractional seconds are present, includes them with 3 decimal places
230
+ # (e.g., ".123")
231
+ # - If the duration is negative, includes the sign prefix
232
+ #
233
+ # This method is used internally by #to_s and can also be called directly
234
+ # for smart formatting using the %D directive.
235
+ #
236
+ # @return [String] a formatted duration string using intelligent component
237
+ # inclusion
123
238
  def format_smart
124
239
  template = '%h:%m:%s'
125
240
  precision = nil
data/lib/tins/expose.rb CHANGED
@@ -1,14 +1,63 @@
1
1
  module Tins
2
+ # A module that provides a way to expose private and protected methods for
3
+ # testing or debugging purposes.
4
+ #
5
+ # This module is particularly useful in test suites where you need to verify
6
+ # internal implementation details without making methods public, or for
7
+ # debugging complex object states during development.
8
+ #
9
+ # @example Basic method exposure
10
+ # obj = MyClass.new
11
+ # exposed_obj = obj.expose
12
+ # exposed_obj.private_method # Accessible now
13
+ #
14
+ # @example Direct method call
15
+ # obj = MyClass.new
16
+ # result = obj.expose(:private_method)
17
+ # # Equivalent to: obj.private_method
18
+ #
19
+ # @example Block execution
20
+ # obj = MyClass.new
21
+ # obj.expose { self.private_method }
22
+ #
23
+ # @example Testing private methods
24
+ # describe MyClass do
25
+ # it "should handle edge cases" do
26
+ # obj = MyClass.new
27
+ # result = obj.expose(:private_calculation, arg1, arg2)
28
+ # expect(result).to eq(expected_value)
29
+ # end
30
+ # end
31
+ #
32
+ # @note This module should only be used in test or debugging contexts.
33
+ # Using it in production code can compromise encapsulation.
34
+ # @note Modifying the exposed object's state may affect the original object
35
+ # since it operates on a duplicated instance.
2
36
  module Expose
3
37
  # Expose any (private/protected) method or internal state of this object
4
38
  # returning the result for specing purposes.
5
39
  #
6
- # @param method_name [ Symbol | String ] name of the method
7
- # (shortcut for reader methods).
8
- # @param block [ Proc ] any private/protected methods of the object can be
9
- # called in this block.
40
+ # This method provides three distinct usage patterns:
10
41
  #
11
- # @return [ Object ] result of the method or block call
42
+ # 1. **Method Call**: When given a method name, directly calls that method
43
+ # and returns its result.
44
+ #
45
+ # 2. **Block Execution**: When given a block, evaluates the block in the
46
+ # context of the object, allowing access to private/protected methods.
47
+ #
48
+ # 3. **Full Exposure**: When called without arguments, returns a duplicate
49
+ # of the object with all private and protected methods exposed as public.
50
+ #
51
+ # @param method_name [Symbol, String, nil] name of the method to call,
52
+ # or nil for full exposure
53
+ # @param args [Array] arguments to pass to the method when calling it
54
+ # @param block [Proc] block to execute in the context of the object
55
+ #
56
+ # @return [Object] result of the method call, block execution, or a new
57
+ # object with exposed methods (when called without args)
58
+ #
59
+ # @raise [NoMethodError] if method_name is given but doesn't exist
60
+ # @raise [ArgumentError] if both method_name and block are provided
12
61
  def expose(method_name = nil, *args, &block)
13
62
  if block
14
63
  instance_eval(&block)
@@ -1,5 +1,14 @@
1
1
  module Tins
2
+ # Extracts the last argument from an array if it responds to to_hash
3
+ #
4
+ # This module provides a method to separate arguments into regular arguments
5
+ # and options (a hash) by checking if the last element responds to to_hash
2
6
  module ExtractLastArgumentOptions
7
+ # Extracts the last argument if it responds to to_hash and returns an array
8
+ # with the remaining elements and the extracted options hash.
9
+ #
10
+ # @return [Array<Object, Hash>] an array containing the sliced array and
11
+ # the extracted options hash
3
12
  def extract_last_argument_options
4
13
  last_argument = last
5
14
  if last_argument.respond_to?(:to_hash) and
@@ -1,37 +1,76 @@
1
1
  module Tins
2
+ # A module for detecting and analyzing binary files based on content patterns
3
+ #
4
+ # This module provides functionality to determine whether a file contains
5
+ # binary data by examining its content against various thresholds for
6
+ # null bytes and high-order bits. It's useful for identifying files that
7
+ # are not plain text, such as images, executables, or other binary formats.
8
+ #
9
+ # The detection is performed by scanning a specified portion of the file
10
+ # and calculating the percentage of bytes that match binary criteria.
2
11
  module FileBinary
12
+ # Constants used for binary detection logic
3
13
  module Constants
14
+ # Seek constant for absolute positioning
4
15
  SEEK_SET = ::File::SEEK_SET
5
16
 
6
- ZERO_RE = "\x00"
7
- BINARY_RE = "\x01-\x1f\x7f-\xff"
17
+ # Regular expression matching null bytes (zero bytes)
18
+ ZERO_RE = +"\x00"
8
19
 
20
+ # Regular expression matching binary bytes (high-order bits set)
21
+ BINARY_RE = +"\x01-\x1f\x7f-\xff"
22
+
23
+ # Ensure proper encoding for Ruby 1.9+
9
24
  if defined?(::Encoding)
10
25
  ZERO_RE.force_encoding(Encoding::ASCII_8BIT)
11
26
  BINARY_RE.force_encoding(Encoding::ASCII_8BIT)
12
27
  end
13
28
  end
14
29
 
30
+ # Default configuration options for binary detection
15
31
  class << self
16
- # Default options can be queried/set via this hash.
32
+ # Accessor for default options hash
17
33
  attr_accessor :default_options
18
34
  end
35
+
36
+ # Configuration hash with sensible defaults for binary file detection
19
37
  self.default_options = {
38
+ # Starting offset for scanning file content
20
39
  offset: 0,
21
- buffer_size: 2 ** 13,
40
+
41
+ # Buffer size in bytes for reading file content
42
+ buffer_size: 2 ** 13, # 8KB
43
+
44
+ # Percentage threshold for binary bytes (high-order bits set)
22
45
  percentage_binary: 30.0,
46
+
47
+ # Percentage threshold for null bytes (zeros)
23
48
  percentage_zeros: 0.0,
24
49
  }
25
50
 
26
- # Returns true if this file is considered to be binary, false if it is not
27
- # considered to be binary, and nil if it was empty.
51
+ # Determines if a file is considered binary based on content analysis
52
+ #
53
+ # A file is classified as binary if either:
54
+ # 1. The percentage of null bytes exceeds the configured threshold
55
+ # 2. The percentage of binary bytes (bytes with high-order bit set) exceeds
56
+ # the configured threshold
57
+ #
58
+ # @param options [Hash] Configuration options for binary detection
59
+ # @option options [Integer] :offset (0) Starting position in file to begin analysis
60
+ # @option options [Integer] :buffer_size (8192) Number of bytes to read for analysis
61
+ # @option options [Float] :percentage_binary (30.0) Binary byte threshold percentage
62
+ # @option options [Float] :percentage_zeros (0.0) Null byte threshold percentage
63
+ #
64
+ # @return [Boolean, nil] true if binary, false if not binary, nil if file is empty
65
+ #
66
+ # @example Basic usage
67
+ # FileBinary.binary?('large_binary_file.dat') # => true
28
68
  #
29
- # A file is considered to be binary if the percentage of zeros exceeds
30
- # <tt>options[:percentage_zeros]</tt> or the percentage of binary bytes
31
- # (8-th bit is 1) exceeds <tt>options[:percentage_binary]</tt> in the
32
- # buffer of size <tt>options[:buffer_size]</tt> that is checked (beginning
33
- # from offset <tt>options[:offset]</tt>). If an option isn't given the one
34
- # from FileBinary.default_options is used instead.
69
+ # @example Custom thresholds
70
+ # FileBinary.binary?('file.txt', percentage_binary: 10.0) # => false
71
+ #
72
+ # @example With offset and buffer size
73
+ # FileBinary.binary?('file.log', offset: 1024, buffer_size: 4096) # => true
35
74
  def binary?(options = {})
36
75
  options = FileBinary.default_options.merge(options)
37
76
  old_pos = tell
@@ -47,9 +86,21 @@ module Tins
47
86
  old_pos and seek old_pos, Constants::SEEK_SET
48
87
  end
49
88
 
50
- # Returns true if FileBinary#binary? returns false, false if
51
- # FileBinary#binary? returns true, and nil otherwise. For an explanation of
52
- # +options+, see FileBinary#binary?.
89
+ # Returns the logical opposite of binary? - true if file is not binary (ASCII/text)
90
+ #
91
+ # @param options [Hash] Configuration options for ASCII detection
92
+ # @option options [Integer] :offset (0) Starting position in file to begin analysis
93
+ # @option options [Integer] :buffer_size (8192) Number of bytes to read for analysis
94
+ # @option options [Float] :percentage_binary (30.0) Binary byte threshold percentage
95
+ # @option options [Float] :percentage_zeros (0.0) Null byte threshold percentage
96
+ #
97
+ # @return [Boolean, nil] true if ASCII/text, false if binary, nil if file is empty
98
+ #
99
+ # @example Basic usage
100
+ # FileBinary.ascii?('script.rb') # => true
101
+ #
102
+ # @example With custom options
103
+ # FileBinary.ascii?('data.bin', percentage_zeros: 5.0) # => false
53
104
  def ascii?(options = {})
54
105
  case binary?(options)
55
106
  when true then false
@@ -57,6 +108,9 @@ module Tins
57
108
  end
58
109
  end
59
110
 
111
+ # Module inclusion hook that extends the including class with ClassMethods
112
+ #
113
+ # @param modul [Module] The module that is including FileBinary
60
114
  def self.included(modul)
61
115
  modul.instance_eval do
62
116
  extend ClassMethods
@@ -64,20 +118,49 @@ module Tins
64
118
  super
65
119
  end
66
120
 
121
+ # Class methods that provide file-level binary detection capabilities
122
+ #
123
+ # These methods allow binary detection without manually opening files
67
124
  module ClassMethods
68
- # Returns true if the file with name +name+ is considered to be binary
69
- # using the FileBinary#binary? method.
125
+ # Determines if a file is considered binary by name
126
+ #
127
+ # @param name [String] Path to the file to analyze
128
+ # @param options [Hash] Configuration options for binary detection
129
+ # @option options [Integer] :offset (0) Starting position in file to begin analysis
130
+ # @option options [Integer] :buffer_size (8192) Number of bytes to read for analysis
131
+ # @option options [Float] :percentage_binary (30.0) Binary byte threshold percentage
132
+ # @option options [Float] :percentage_zeros (0.0) Null byte threshold percentage
133
+ #
134
+ # @return [Boolean, nil] true if binary, false if not binary, nil if file is empty
135
+ #
136
+ # @example Basic usage
137
+ # FileBinary.binary?('config.json') # => false
138
+ #
139
+ # @example With custom options
140
+ # FileBinary.binary?('data.dat', percentage_binary: 25.0) # => true
70
141
  def binary?(name, options = {})
71
142
  open(name, 'rb') { |f| f.binary?(options) }
72
143
  end
73
144
 
74
- # Returns true if the file with name +name+ is considered to be ascii
75
- # using the FileBinary#ascii? method.
145
+ # Determines if a file is considered ASCII/text by name
146
+ #
147
+ # @param name [String] Path to the file to analyze
148
+ # @param options [Hash] Configuration options for ASCII detection
149
+ # @option options [Integer] :offset (0) Starting position in file to begin analysis
150
+ # @option options [Integer] :buffer_size (8192) Number of bytes to read for analysis
151
+ # @option options [Float] :percentage_binary (30.0) Binary byte threshold percentage
152
+ # @option options [Float] :percentage_zeros (0.0) Null byte threshold percentage
153
+ #
154
+ # @return [Boolean, nil] true if ASCII/text, false if binary, nil if file is empty
155
+ #
156
+ # @example Basic usage
157
+ # FileBinary.ascii?('readme.md') # => true
158
+ #
159
+ # @example With custom options
160
+ # FileBinary.ascii?('binary_file.dat', percentage_zeros: 10.0) # => false
76
161
  def ascii?(name, options = {})
77
162
  open(name, 'rb') { |f| f.ascii?(options) }
78
163
  end
79
164
  end
80
165
  end
81
166
  end
82
-
83
- require 'tins/alias'