tins 1.38.0 → 1.51.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 (118) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES.md +159 -0
  3. data/README.md +158 -6
  4. data/Rakefile +28 -18
  5. data/examples/let.rb +8 -40
  6. data/examples/mail.rb +0 -1
  7. data/examples/turing.rb +3 -1
  8. data/lib/tins/alias.rb +1 -0
  9. data/lib/tins/annotate.rb +37 -27
  10. data/lib/tins/ask_and_send.rb +41 -0
  11. data/lib/tins/attempt.rb +39 -0
  12. data/lib/tins/bijection.rb +34 -0
  13. data/lib/tins/case_predicate.rb +21 -0
  14. data/lib/tins/complete.rb +16 -0
  15. data/lib/tins/concern.rb +64 -0
  16. data/lib/tins/date_dummy.rb +36 -4
  17. data/lib/tins/date_time_dummy.rb +34 -2
  18. data/lib/tins/deep_dup.rb +9 -2
  19. data/lib/tins/deprecate.rb +12 -0
  20. data/lib/tins/dslkit.rb +563 -59
  21. data/lib/tins/duration.rb +120 -5
  22. data/lib/tins/expose.rb +54 -5
  23. data/lib/tins/extract_last_argument_options.rb +9 -0
  24. data/lib/tins/file_binary.rb +104 -21
  25. data/lib/tins/find.rb +114 -11
  26. data/lib/tins/generator.rb +10 -2
  27. data/lib/tins/go.rb +78 -14
  28. data/lib/tins/hash_bfs.rb +4 -2
  29. data/lib/tins/hash_symbolize_keys_recursive.rb +62 -4
  30. data/lib/tins/hash_union.rb +47 -2
  31. data/lib/tins/if_predicate.rb +31 -0
  32. data/lib/tins/implement.rb +50 -0
  33. data/lib/tins/limited.rb +63 -12
  34. data/lib/tins/lines_file.rb +81 -2
  35. data/lib/tins/lru_cache.rb +54 -17
  36. data/lib/tins/memoize.rb +86 -58
  37. data/lib/tins/method_description.rb +87 -4
  38. data/lib/tins/minimize.rb +39 -11
  39. data/lib/tins/module_group.rb +27 -2
  40. data/lib/tins/named_set.rb +20 -0
  41. data/lib/tins/null.rb +86 -15
  42. data/lib/tins/once.rb +61 -4
  43. data/lib/tins/p.rb +44 -8
  44. data/lib/tins/partial_application.rb +66 -7
  45. data/lib/tins/proc_compose.rb +58 -1
  46. data/lib/tins/proc_prelude.rb +97 -10
  47. data/lib/tins/range_plus.rb +30 -2
  48. data/lib/tins/require_maybe.rb +36 -0
  49. data/lib/tins/responding.rb +39 -0
  50. data/lib/tins/secure_write.rb +24 -4
  51. data/lib/tins/sexy_singleton.rb +45 -48
  52. data/lib/tins/string_byte_order_mark.rb +33 -2
  53. data/lib/tins/string_camelize.rb +31 -2
  54. data/lib/tins/string_named_placeholders.rb +70 -0
  55. data/lib/tins/string_underscore.rb +33 -2
  56. data/lib/tins/string_version.rb +190 -12
  57. data/lib/tins/subhash.rb +35 -10
  58. data/lib/tins/temp_io.rb +7 -0
  59. data/lib/tins/temp_io_enum.rb +19 -0
  60. data/lib/tins/terminal.rb +31 -9
  61. data/lib/tins/thread_local.rb +67 -5
  62. data/lib/tins/time_dummy.rb +46 -21
  63. data/lib/tins/to.rb +15 -0
  64. data/lib/tins/to_proc.rb +17 -4
  65. data/lib/tins/token.rb +74 -2
  66. data/lib/tins/unit.rb +304 -149
  67. data/lib/tins/version.rb +1 -1
  68. data/lib/tins/write.rb +14 -3
  69. data/lib/tins/xt/blank.rb +81 -2
  70. data/lib/tins/xt/concern.rb +51 -0
  71. data/lib/tins/xt/deep_dup.rb +4 -2
  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/secure_write.rb +0 -4
  79. data/lib/tins/xt/string.rb +1 -0
  80. data/lib/tins/xt/string_camelize.rb +4 -2
  81. data/lib/tins/xt/string_named_placeholders.rb +7 -0
  82. data/lib/tins/xt/string_underscore.rb +4 -2
  83. data/lib/tins/xt/subhash.rb +11 -0
  84. data/lib/tins/xt/time_freezer.rb +43 -6
  85. data/lib/tins/xt/write.rb +0 -4
  86. data/lib/tins/xt.rb +1 -3
  87. data/lib/tins.rb +17 -3
  88. data/tests/dslkit_test.rb +15 -0
  89. data/tests/duration_test.rb +4 -0
  90. data/tests/from_module_test.rb +30 -2
  91. data/tests/go_test.rb +4 -2
  92. data/tests/implement_test.rb +6 -8
  93. data/tests/limited_test.rb +1 -1
  94. data/tests/lines_file_test.rb +2 -0
  95. data/tests/lru_cache_test.rb +12 -0
  96. data/tests/method_description_test.rb +14 -20
  97. data/tests/partial_application_test.rb +4 -0
  98. data/tests/proc_prelude_test.rb +1 -1
  99. data/tests/scope_test.rb +1 -1
  100. data/tests/string_named_placeholders.rb +109 -0
  101. data/tests/string_version_test.rb +15 -0
  102. data/tests/test_helper.rb +4 -5
  103. data/tests/to_test.rb +6 -6
  104. data/tests/token_test.rb +32 -1
  105. data/tests/unit_test.rb +18 -0
  106. data/tins.gemspec +13 -11
  107. metadata +49 -33
  108. data/lib/tins/count_by.rb +0 -21
  109. data/lib/tins/deep_const_get.rb +0 -64
  110. data/lib/tins/timed_cache.rb +0 -51
  111. data/lib/tins/uniq_by.rb +0 -23
  112. data/lib/tins/xt/count_by.rb +0 -7
  113. data/lib/tins/xt/deep_const_get.rb +0 -7
  114. data/lib/tins/xt/uniq_by.rb +0 -25
  115. data/tests/count_by_test.rb +0 -17
  116. data/tests/deep_const_get_test.rb +0 -37
  117. data/tests/uniq_by_test.rb +0 -31
  118. /data/{COPYING → LICENSE} +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 26f2a6faf004d28bc511820eb58835ba4b555481d38b12839b264fde8664b321
4
- data.tar.gz: 394319369bf23b6afee56aebfe70ebdebe9d4d05ff77181338a754f667921266
3
+ metadata.gz: '0842c03ef937e88e3983fe986604f369f741c783d5aeb1f73a27d50f98512265'
4
+ data.tar.gz: aeaf30f783e232586deb4b60017623539d37973a035331050c5d4c75c9af1f72
5
5
  SHA512:
6
- metadata.gz: 6491996c174a13ec0a4b1cbd8c2437e7f7becca98965962a0aa446e7a7bd50f87ef8ebef4ba61dc0c48b38a97a0009ee1b6411a414c42ca53903f97a9e025861
7
- data.tar.gz: cc785591e2c3efe72b0b70585dd30001bf5d4e6d7ff6b8b1b88c023c7be85bc6cb1ca7262e9b3ace3a009f4eac39ca2b9cf62dea73858bd0dd570292b583c62d
6
+ metadata.gz: fc76519aa6e09ff9a9e8094712070f71be2f34540a4001af2f6f07c5de357ac8642230828d543ffa53219936bf877db88e02e6dfb3a6f713e312b236b45e3d2a
7
+ data.tar.gz: 9e65ecc2199824d5efafb4502c9c5bef6322c5e9cad8f9f72504bb0571d09b15251e539db7b6336cad0af161e382bb2bf473fcaf720d2f146a6dba3b2757f84f
data/CHANGES.md CHANGED
@@ -1,5 +1,164 @@
1
1
  # Changes
2
2
 
3
+ ## 2025-12-20 v1.51.0
4
+
5
+ - Added `readline` as a runtime dependency in both `Rakefile` and
6
+ `tins.gemspec`
7
+ - The `readline` dependency version is set to `>= 0` in `tins.gemspec`
8
+ - The `readline` dependency is added to the `GemHadar` block in `Rakefile`
9
+
10
+ ## 2025-12-19 v1.50.0
11
+
12
+ - Updated `gem_hadar` development dependency version to **2.10**
13
+ - Added `ruby:4.0-rc-alpine` image to the `images` section in `.all_images.yml`
14
+
15
+ ## 2025-12-18 v1.49.0
16
+
17
+ - Updated `bundle update` command to `bundle update --all` in `.all_images.yml`
18
+ to ensure all dependencies are updated recursively
19
+ - Added support for IEC binary prefixes with new `PREFIX_IEC_UC` constant and
20
+ updated `prefixes` method to handle `:iec_uc` and `:iec_uppercase`
21
+ identifiers
22
+ - Added corresponding test cases for IEC prefix mapping
23
+ - Added `:si_greek` alias for fractional prefixes (`m`, `µ`, `n`, etc.) in `PREFIX_F`
24
+ - Added `:si_uppercase` alias for SI uppercase prefixes (`K`, `M`, `G`, etc.) in `PREFIX_SI_UC`
25
+ - Updated `PREFIX_SI_UC` comment to clarify these are based on **1000**-step increments, not 1024
26
+ - Enhanced `prefixes` method to support new aliases while maintaining backward compatibility
27
+ - Added comprehensive tests for new aliases in `Tins::UnitTest`
28
+ - Updated `s.rubygems_version` from **3.7.2** to **4.0.2** in gemspec
29
+
30
+ ## 2025-12-05 v1.48.0
31
+
32
+ - Added `Tins::Token.analyze` class method to calculate bit strength
33
+ - Moved bit calculation logic from `initialize` to `analyze` method for reuse
34
+ - Implemented bit strength calculation using formula: `length ×
35
+ log₂(alphabet_size)`
36
+ - Added comprehensive tests for the `analyze` method with various alphabets
37
+ - Support both token string and length-based analysis
38
+ - Implemented proper error handling for required parameters
39
+ - Updated `initialize` method to use the new `analyze` method
40
+ - Test cases verify bit strength for **BASE16**, **BASE64**, and **BASE32**
41
+ alphabets
42
+ - Method returns integer bit strength for cryptographic token analysis
43
+
44
+ ## 2025-11-14 v1.47.0
45
+
46
+ - Tins::GO
47
+ - Renamed `EnumerableExtension` module to `ArrayExtension` throughout the
48
+ codebase
49
+ - Updated method calls from `<<` to `push` for consistency with
50
+ `ArrayExtension`
51
+ - Modified `to_a` method implementation to return `@arguments` directly
52
+ - Updated test assertions to expect `ArrayExtension` instead of
53
+ `EnumerableExtension`
54
+ - Changed documentation comments to reflect the new `ArrayExtension` name
55
+ - Updated type checking from `EnumerableExtension` to `ArrayExtension` in
56
+ conditional logic
57
+
58
+ ## 2025-11-10 v1.46.0
59
+
60
+ - Updated `s.rubygems_version` from **3.6.9** to **3.7.2** in gemspec
61
+ - In Tins::GO
62
+ - Extended string defaults with `EnumerableExtension` transformation
63
+ - Modified `v.transform_values!` to check and extend strings that aren't already `EnumerableExtension`
64
+ - Applied `w << w` to properly initialize the extension on default strings
65
+ - Updated tests to verify `EnumerableExtension` instances for both `v` and `w` options
66
+ - Set default value for `?w` option to **'baz'** in test cases
67
+ - Maintained backward compatibility while normalizing string handling
68
+ - Ensured consistent behavior between ARGV strings and default strings
69
+
70
+ ## 2025-10-16 v1.45.0
71
+
72
+ - Added `patch` alias for `build` and `build=` methods to align with SemVer terminology
73
+ - Updated `LEVELS` mapping to support `:patch` as alias for `:build` index
74
+ - Added `patch` and `patch=` aliases using the `alias` method
75
+ - Added tests for `patch` getter and setter functionality
76
+ - Updated `gem_hadar` development dependency from version **2.5** to **2.8**
77
+ - Added `openssl-dev` to Docker build dependencies
78
+ - Added `github_workflows` configuration to `Rakefile` for `static.yml` workflow
79
+ - Removed `.byebug_history` from `.gitignore` file
80
+ - Removed `.byebug_history` from ignore list in `Rakefile`
81
+ - Removed duplicate `mize` entry from code indexer configuration
82
+
83
+ ## 2025-09-13 v1.44.1
84
+
85
+ - Updated documentation link in README.md to point to GitHub.io instead of
86
+ RubyDoc.info
87
+ - Added graceful handling for missing `gem_hadar/simplecov` gem by wrapping
88
+ require and start in begin/rescue block to catch `LoadError`
89
+ - Modified gem packaging to include all files in `.github` and `.contexts` directories using `FileList` for dynamic inclusion
90
+ - Created `static.yml` file
91
+
92
+ ## 2025-09-12 v1.44.0
93
+
94
+ ### Major Changes
95
+
96
+ - **Ruby Version Requirement**: Updated minimum Ruby version requirement to 3.1
97
+ - **Dependency Modernization**: Replaced deprecated `Tins::Memoize` module
98
+ implementation with `mize` gem for memoization functionality
99
+ - **Documentation Overhaul**: Comprehensive YARD documentation added across all
100
+ modules with examples and parameter descriptions
101
+ - **README Enhancement**: Improved README.md with better documentation,
102
+ examples, and usage instructions
103
+
104
+ ## 2025-09-05 v1.43.0
105
+
106
+ - Added new `dsl_lazy_accessor` method that creates lazy-loaded accessors with
107
+ support for default blocks and dynamic block assignment
108
+ - Removed support for Ruby versions **3.1** and **3.0** from image definitions
109
+
110
+ ## 2025-08-19 v1.42.0
111
+
112
+ - Improved core class extension safety by using `respond_to?` checks to avoid
113
+ overriding existing methods such as `deep_dup`, `camelize`, and `underscore`
114
+ - Simplified GitHub directory ignore patterns in `Rakefile` by removing
115
+ recursive glob pattern for `.github` directory and directly specifying it as
116
+ a single entry
117
+ - Added documentation context files and YARD cheatsheet, including `.contexts/`
118
+ directory with code comment examples and updated `Rakefile` and
119
+ `tins.gemspec` to include context files and `context_spook` dependency
120
+
121
+ ## 2025-08-18 v1.41.0
122
+
123
+ - Added new `named_placeholders_interpolate` method for template substitution
124
+ - Method supports both static and dynamic default values via Proc
125
+ - Maintains backward compatibility with existing `named_placeholders_assign` method
126
+ - Includes comprehensive tests for all functionality and error handling
127
+ - Uses `named_placeholders_assign` internally for consistent implementation
128
+
129
+ ## 2025-08-18 v1.40.0
130
+
131
+ - Added `Tins::StringNamedPlaceholders` module with `named_placeholders` and
132
+ `named_placeholders_assign` methods for string template substitution
133
+ - Implemented support for both static and dynamic default values using Proc
134
+ objects
135
+ - Extended `String` class with `tins/xt/string` to include the new named
136
+ placeholders functionality
137
+ - Enhanced test coverage with comprehensive tests for all named placeholders
138
+ functionality including error handling and duplicate placeholder management
139
+ - Replaced manual SimpleCov setup with `GemHadar::SimpleCov.start` in test
140
+ helper
141
+
142
+ ## 2025-07-30 v1.39.1
143
+
144
+ - Updated `gem_hadar` development dependency to version **1.22**
145
+ - Bumped version from '1.39.0' to '1.39.1' in lib/tins/version.rb
146
+ - Updated `s.version` in tins.gemspec from "1.39.0" to "1.39.1"
147
+ - Updated stub version in tins.gemspec from **1.39.0** to **1.39.1**
148
+
149
+ ## 2025-07-30 v1.39.0
150
+
151
+ - Updated `VERSION` constant in `lib/tins/version.rb` from **1.38.0** to **1.39.0**
152
+ - Updated gem stub and version in `tins.gemspec`
153
+ - Updated `s.rubygems_version` from **3.6.2** to **3.6.9**
154
+ - Updated `s.add_development_dependency :gem_hadar` from ~> **1.19** to ~> **1.21**
155
+ - Added support for thread naming in `Limited` class
156
+ - Added `name` parameter to `Limited#initialize`
157
+ - Set `@name` attribute when provided
158
+ - Set executor name with `@name` if available
159
+ - Updated tests to use named threads
160
+ - Removed `binary` option from discover block in `.utilsrc`
161
+
3
162
  ## 2025-01-04 v1.38.0
4
163
 
5
164
  * Improved Tins::Limited concurrency handling:
data/README.md CHANGED
@@ -2,18 +2,170 @@
2
2
 
3
3
  ## Description
4
4
 
5
- Non yet.
5
+ A collection of useful Ruby utilities that extend the standard library with
6
+ practical conveniences. Tins provides lightweight, dependency-free tools for
7
+ common programming tasks.
6
8
 
7
- ## Badges
9
+ ## Documentation
8
10
 
9
- [![Code Climate](https://codeclimate.com/github/flori/tins.png)](https://codeclimate.com/github/flori/tins)
11
+ Complete API documentation is available at: [GitHub.io](https://flori.github.io/tins/)
10
12
 
11
- [![Code Coverage](https://codeclimate.com/github/flori/tins/coverage.png)](https://codeclimate.com/github/flori/tins)
13
+ ## Installation
14
+
15
+ Add this line to your application's Gemfile:
16
+
17
+ ```ruby
18
+ gem 'tins'
19
+ ```
20
+
21
+ Or:
22
+
23
+ ```ruby
24
+ gem 'tins', require 'tins/xt'
25
+ ```
26
+
27
+ to automatically extend some core classes with useful methods.
28
+
29
+ And then execute:
30
+
31
+ $ bundle install
32
+
33
+ Or install it yourself as:
34
+
35
+ $ gem install tins
36
+
37
+ ## Usage
38
+
39
+ ```ruby
40
+ # Load all utilities
41
+
42
+ require 'tins'
43
+
44
+ # Load all utilities and extends core classes with useful methods
45
+ require 'tins/xt'
46
+ ```
47
+ ## Some Usage Examples
48
+
49
+ ### Duration Handling
50
+
51
+ ```ruby
52
+ require 'tins/duration'
53
+
54
+ duration = Tins::Duration.new(9000)
55
+ puts duration.to_s # "02:30:00"
56
+ puts duration.to_i # 9000 (seconds)
57
+
58
+ # Parse durations from strings
59
+ Tins::Duration.parse('2h 30m', template: '%hh %mm') # 9000 (seconds)
60
+ ```
61
+
62
+ ### Unit Conversion
63
+
64
+ ```ruby
65
+ require 'tins/unit'
66
+
67
+ bytes = Tins::Unit.parse('1.5 GB', unit: ?B).to_i # => 1610612736
68
+ puts Tins::Unit.format(bytes, unit: 'B') # "1.500000 GB"
69
+ ```
70
+
71
+ ### Secure File Writing
72
+
73
+ ```ruby
74
+ require 'tins/xt/secure_write'
75
+
76
+ # Write files safely (atomic operation)
77
+ File.secure_write('config.json', '{"key": "value"}')
78
+ ```
79
+
80
+ ### Time Freezing for Testing
81
+
82
+ ```ruby
83
+ require 'tins/xt/time_freezer'
84
+
85
+ # Freeze time during testing
86
+ Tins::TimeFreezer.freeze(Time.new('2011-12-13 14:15:16')) do
87
+ puts Time.now # Always returns the frozen time
88
+ end
89
+ ```
90
+
91
+ ### Building blocks for DSLs
92
+
93
+ ```ruby
94
+ class Foo
95
+ include Tins::DynamicScope
96
+
97
+ def let(bindings = {})
98
+ dynamic_scope do
99
+ bindings.each { |name, value| send("#{name}=", value) }
100
+ yield
101
+ end
102
+ end
103
+
104
+ def twice(x)
105
+ 2 * x
106
+ end
107
+
108
+ def test
109
+ let x: 1, y: twice(1) do
110
+ let z: twice(x) do
111
+ "#{x} * #{y} == #{z} # => #{x * y == twice(x)}"
112
+ end
113
+ end
114
+ end
115
+ end
116
+
117
+ Foo.new.test # "1 * 2 == 2 # => true"
118
+ ```
119
+
120
+ ### Core Class Extensions (xt)
121
+
122
+ When you require `tins/xt`, some useful methods are added to core classes:
123
+
124
+ ```ruby
125
+ default_options = {
126
+ format: :json,
127
+ timeout: 30,
128
+ retries: 3
129
+ }
130
+
131
+ user_options = { timeout: 60 }
132
+ options = user_options | default_options
133
+ # => { format: :json, timeout: 60, retries: 3 }
134
+
135
+ '1.10.3'.version < '1.9.2'.version # => false
136
+
137
+ add_one = -> x { x + 1 }
138
+ multiply_by_two = -> x { x * 2 }
139
+ composed = multiply_by_two * add_one
140
+ composed.(5) # => 12
141
+
142
+ # For Testing
143
+ >> o = Object.new
144
+ >> o.puts # => private method, NoMethodError
145
+ >> o = o.expose
146
+ >> o.puts "hello"
147
+ hello
148
+ ```
149
+
150
+ ### Hash Symbolization
151
+
152
+ ```ruby
153
+ require 'tins/hash_symbolize_keys_recursive'
154
+
155
+ hash = {
156
+ 'name' => 'John',
157
+ 'age' => 30,
158
+ 'address' => {
159
+ 'street' => '123 Main St'
160
+ }
161
+ }
162
+ hash.symbolize_keys_recursive! # Converts all keys to symbols recursively
163
+ ```
12
164
 
13
165
  ## Author
14
166
 
15
- Florian Frank mailto:flori@ping.de
167
+ [Florian Frank](mailto:flori@ping.de)
16
168
 
17
169
  ## License
18
170
 
19
- This software is licensed under the MIT (Expat) license.
171
+ [MIT License](./LICENSE)
data/Rakefile CHANGED
@@ -3,28 +3,38 @@
3
3
  require 'gem_hadar'
4
4
 
5
5
  GemHadar do
6
- name 'tins'
7
- author 'Florian Frank'
8
- email 'flori@ping.de'
9
- homepage "https://github.com/flori/#{name}"
10
- summary 'Useful stuff.'
11
- description 'All the stuff that isn\'t good/big enough for a real library.'
12
- test_dir 'tests'
6
+ name 'tins'
7
+ author 'Florian Frank'
8
+ email 'flori@ping.de'
9
+ homepage "https://github.com/flori/#{name}"
10
+ summary 'Useful stuff.'
11
+ description 'All the stuff that isn\'t good/big enough for a real library.'
12
+ test_dir 'tests'
13
13
  test_files.concat Dir["#{test_dir}/*_test.rb"]
14
- ignore '.*.sw[pon]', 'pkg', 'Gemfile.lock', '.rvmrc', 'coverage', '.rbx',
15
- '.AppleDouble', '.DS_Store', 'tags', '.bundle', '.byebug_history'
16
- package_ignore '.all_images.yml', '.tool-versions', '.gitignore', 'VERSION',
17
- '.utilsrc', 'TODO', *Dir.glob('.github/**/*', File::FNM_DOTMATCH)
14
+ doc_code_files files.grep(%r(\Alib/))
15
+ ignore '.*.sw[pon]', 'pkg', 'Gemfile.lock', '.rvmrc', 'coverage',
16
+ '.rbx', '.AppleDouble', '.DS_Store', 'tags', 'cscope.out', '.bundle',
17
+ '.yardoc', 'doc', 'TODO.md'
18
+ package_ignore '.all_images.yml', '.tool-versions', '.gitignore',
19
+ 'VERSION', '.utilsrc', '.github', '.contexts'
18
20
 
19
- readme 'README.md'
20
- licenses << 'MIT'
21
+ readme 'README.md'
22
+ licenses << 'MIT'
23
+ clean << 'coverage'
21
24
 
22
- required_ruby_version '>= 2.0'
25
+ github_workflows(
26
+ 'static.yml' => {}
27
+ )
28
+
29
+ required_ruby_version '>= 3.1'
30
+
31
+ dependency 'sync'
32
+ dependency 'bigdecimal'
33
+ dependency 'readline'
34
+ dependency 'mize', '~> 0.6'
23
35
  development_dependency 'all_images'
24
36
  development_dependency 'debug'
25
- development_dependency 'term-ansicolor'
26
- development_dependency 'test-unit', '~>3.1'
27
37
  development_dependency 'simplecov'
28
- dependency 'sync'
29
- dependency 'bigdecimal'
38
+ development_dependency 'term-ansicolor'
39
+ development_dependency 'test-unit', '~> 3.7'
30
40
  end
data/examples/let.rb CHANGED
@@ -2,48 +2,16 @@
2
2
 
3
3
  require 'tins'
4
4
 
5
- LetScope = Tins::BlankSlate.with :instance_eval, :to_s, :inspect, :extend
6
- class LetScope
7
- include Tins::MethodMissingDelegator::DelegatorModule
8
- include Tins::BlockSelf
9
-
10
- def initialize(my_self, bindings = {}, outer_scope = nil)
11
- super(my_self)
12
- @outer_scope = outer_scope
13
- @bindings = bindings
14
- extend Tins::Eigenclass
15
- eigenclass_eval { extend Tins::Constant }
16
- each_binding do |name, value|
17
- eigenclass_eval { constant name, value }
18
- end
19
- end
20
-
21
- def each_binding(&block)
22
- if @outer_scope
23
- @outer_scope.each_binding(&block)
24
- end
25
- @bindings.each(&block)
26
- end
27
-
28
- def let(bindings = {}, &block)
29
- ls = LetScope.new(block_self(&block), bindings, self)
30
- ls.instance_eval(&block)
31
- end
32
-
33
- # Including this module into your current namespace defines the let method.
34
- module Include
35
- include Tins::BlockSelf
36
-
37
- def let(bindings = {}, &block)
38
- ls = LetScope.new(block_self(&block), bindings)
39
- ls.instance_eval(&block)
40
- end
41
- end
42
- end
43
-
44
5
  if $0 == __FILE__
45
6
  class Foo
46
- include LetScope::Include
7
+ include Tins::DynamicScope
8
+
9
+ def let(bindings = {})
10
+ dynamic_scope do
11
+ bindings.each { |name, value| send("#{name}=", value) }
12
+ yield
13
+ end
14
+ end
47
15
 
48
16
  def twice(x)
49
17
  2 * x
data/examples/mail.rb CHANGED
@@ -6,7 +6,6 @@ require 'time'
6
6
 
7
7
  class Mail
8
8
  extend Tins::DSLAccessor
9
- include Tins::InstanceExec
10
9
  include Tins::MethodMissingDelegator::DelegatorModule
11
10
  include Tins::BlockSelf
12
11
 
data/examples/turing.rb CHANGED
@@ -307,6 +307,8 @@ if $0 == __FILE__ and ARGV.any?
307
307
  else
308
308
  raise "unknown turing machine suffix: #{ext}, use .stm or .mtm"
309
309
  end
310
- tm = machine_type.new(File.read(filename))
310
+ tm = File.open(filename) do |file|
311
+ machine_type.new(file)
312
+ end
311
313
  $DEBUG ? tm.step(*tapes) : tm.run(*tapes)
312
314
  end
data/lib/tins/alias.rb CHANGED
@@ -1 +1,2 @@
1
+ # This Is Not Spruz
1
2
  Spruz = Tins
data/lib/tins/annotate.rb CHANGED
@@ -1,38 +1,48 @@
1
- module Tins::Annotate
2
- def annotate(name)
3
- singleton_class.class_eval do
4
- define_method(name) do |annotation = :annotated|
5
- instance_variable_set "@__annotation_#{name}__", annotation
6
- end
1
+ module Tins
2
+ # A module for adding annotations to classes and methods
3
+ #
4
+ # This module provides functionality to add metadata annotations to classes and
5
+ # methods, allowing for enhanced documentation and introspection capabilities
6
+ module Annotate
7
+ # The annotate method sets up annotation functionality for a given name
8
+ # by defining methods to set and retrieve annotations on class methods
9
+ #
10
+ # @param name [ Symbol ] the name of the annotation to define
11
+ def annotate(name)
12
+ singleton_class.class_eval do
13
+ define_method(name) do |annotation = :annotated|
14
+ instance_variable_set "@__annotation_#{name}__", annotation
15
+ end
7
16
 
8
- define_method("#{name}_of") do |method_name|
9
- __send__("#{name}_annotations")[method_name]
10
- end
17
+ define_method("#{name}_of") do |method_name|
18
+ __send__("#{name}_annotations")[method_name]
19
+ end
11
20
 
12
- define_method("#{name}_annotations") do
13
- if instance_variable_defined?("@__annotation_#{name}_annotations__")
14
- instance_variable_get "@__annotation_#{name}_annotations__"
15
- else
16
- instance_variable_set "@__annotation_#{name}_annotations__", {}
21
+ define_method("#{name}_annotations") do
22
+ if instance_variable_defined?("@__annotation_#{name}_annotations__")
23
+ instance_variable_get "@__annotation_#{name}_annotations__"
24
+ else
25
+ instance_variable_set "@__annotation_#{name}_annotations__", {}
26
+ end
17
27
  end
18
- end
19
28
 
20
- old_method_added = instance_method(:method_added)
21
- define_method(:method_added) do |method_name|
22
- old_method_added.bind(self).call method_name
23
- if annotation = instance_variable_get("@__annotation_#{name}__")
24
- __send__("#{name}_annotations")[method_name] = annotation
29
+ old_method_added = instance_method(:method_added)
30
+ define_method(:method_added) do |method_name|
31
+ old_method_added.bind(self).call method_name
32
+ if annotation = instance_variable_get("@__annotation_#{name}__")
33
+ __send__("#{name}_annotations")[method_name] = annotation
34
+ end
35
+ instance_variable_set "@__annotation_#{name}__", nil
25
36
  end
26
- instance_variable_set "@__annotation_#{name}__", nil
27
37
  end
28
- end
29
38
 
30
- define_method("#{name}_annotations") do
31
- self.class.__send__("#{name}_annotations")
32
- end
39
+ define_method("#{name}_annotations") do
40
+ self.class.__send__("#{name}_annotations")
41
+ end
33
42
 
34
- define_method("#{name}_of") do |method_name|
35
- self.class.__send__("#{name}_of", method_name)
43
+ define_method("#{name}_of") do |method_name|
44
+ self.class.__send__("#{name}_of", method_name)
45
+ end
36
46
  end
37
47
  end
38
48
  end
@@ -1,17 +1,47 @@
1
1
  module Tins
2
+ # A module that provides methods to call private and protected methods on
3
+ # objects.
2
4
  module AskAndSend
5
+ # The ask_and_send method attempts to invoke a given method on the object
6
+ # if that method is available.
7
+ #
8
+ # @param method_name [ Symbol ] the name of the method to invoke
9
+ # @param args [ Array ] arguments to pass to the method
10
+ # @yield [ block ] optional block to pass to the method
11
+ # @return [ Object, nil ] the result of the method call or nil if the
12
+ # method doesn't exist
3
13
  def ask_and_send(method_name, *args, &block)
4
14
  if respond_to?(method_name)
5
15
  __send__(method_name, *args, &block)
6
16
  end
7
17
  end
8
18
 
19
+ # The ask_and_send! method attempts to invoke a private or protected method
20
+ # on the object.
21
+ #
22
+ # @param method_name [ Symbol ] the name of the method to call
23
+ # @param args [ Array ] arguments to pass to the method
24
+ # @param block [ Proc ] optional block to pass to the method
25
+ #
26
+ # @return [ Object, nil ] the result of the method call or nil if the
27
+ # method doesn't exist
9
28
  def ask_and_send!(method_name, *args, &block)
10
29
  if respond_to?(method_name, true)
11
30
  __send__(method_name, *args, &block)
12
31
  end
13
32
  end
14
33
 
34
+ # The ask_and_send_or_self method attempts to invoke the specified method
35
+ # on the object If the method exists, it calls the method with the provided
36
+ # arguments and block If the method does not exist, it returns the object
37
+ # itself
38
+ #
39
+ # @param method_name [ Symbol ] the name of the method to call
40
+ # @param args [ Array ] the arguments to pass to the method
41
+ # @param block [ Proc ] the block to pass to the method
42
+ #
43
+ # @return [ Object ] the result of the method call or self if the method
44
+ # doesn't exist
15
45
  def ask_and_send_or_self(method_name, *args, &block)
16
46
  if respond_to?(method_name)
17
47
  __send__(method_name, *args, &block)
@@ -20,6 +50,17 @@ module Tins
20
50
  end
21
51
  end
22
52
 
53
+ # The ask_and_send_or_self! method attempts to send a message to the object
54
+ # with the given method name and arguments. If the object responds to the
55
+ # method, it executes the method and returns the result. If the object does
56
+ # not respond to the method, it returns the object itself.
57
+ #
58
+ # @param method_name [ Symbol ] the name of the method to send
59
+ # @param args [ Array ] the arguments to pass to the method
60
+ # @param block [ Proc ] the block to pass to the method
61
+ #
62
+ # @return [ Object ] the result of the method call or the object itself if
63
+ # the method is not found
23
64
  def ask_and_send_or_self!(method_name, *args, &block)
24
65
  if respond_to?(method_name, true)
25
66
  __send__(method_name, *args, &block)