crystal_goodies 1.0.0 → 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 100fad08a9578a26ae53785926cc01fc7d81735a7afe55c62d1a3d74d9312924
4
- data.tar.gz: c0bf1b1c3d290359d270659de2e888fa9486473eae55e517af9c38358c4367af
3
+ metadata.gz: 1ea56dd113383c09a481ff17f3a762e3e7924a1b471404ab97cb3a86ea813cdd
4
+ data.tar.gz: 6306d0c2152e93bc8ac5bfc54c2936ddec63be85f2fc874cacd59e5b236ccf44
5
5
  SHA512:
6
- metadata.gz: 1eebd55c21f807d34ae9be8bacd3c12d645ff9eacc721314bdd19cd3c880091a39d873dee0f3d5e1e5cbd407a0574a695cdc25d5da7ee4fda01f2c5d19c32122
7
- data.tar.gz: f2d138d8a5b01fc8dc89e5913909e0c768332e43c9f1e07ffd2329b98238bc9f84b24316a270698ddff48f89bcd7b54ed2aeba32d334518ab4b253cc49510b69
6
+ metadata.gz: c7085bd6883530c41ed175e8c61ec906df0e082d455584c24f681a37a952427184fb4dd7f2deac06f7b280f63505fe6b0120535cf6b1f247858a631cea9c051a
7
+ data.tar.gz: bfa816894dc44a773cb94ab0e68f6906d30e296e7f2dd5379fef9cf62ab040c41637f3e859bd6fad36b2e87e357f32c4c7d80a8fbf14b5dcc6b6579d49ea8e6d
data/CHANGELOG.md CHANGED
@@ -1,3 +1,11 @@
1
+ ## [1.0.2] - 2023-08-16
2
+
3
+ - Added API documents.
4
+
5
+ ## [1.0.1] - 2023-08-16
6
+
7
+ - Fixed `String#underscore`.
8
+
1
9
  ## [1.0.0] - 2023-08-16
2
10
 
3
11
  - Initial release.
data/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  ## 💡 About
4
4
 
5
- Class's methods port from Crystal.
5
+ Class's methods convenient for scripting port from Crystal.
6
6
 
7
7
  ## 📥 Installation
8
8
 
@@ -25,10 +25,276 @@ In Ruby do:
25
25
  ```rb
26
26
  require 'crystal_goodies'
27
27
  ```
28
- TODO
28
+
29
+ Only require methods to access through module `CrystalGoodies`.
30
+
31
+ ```rb
32
+ require 'crystal_goodies/object'
33
+ require 'crystal_goodies/integer'
34
+ require 'crystal_goodies/string'
35
+ require 'crystal_goodies/array'
36
+ require 'crystal_goodies/enumerable'
37
+ ```
38
+
39
+ Only require class extensions.
40
+
41
+ ```rb
42
+ require 'crystal_goodies/object/extensions'
43
+ require 'crystal_goodies/integer/extensions'
44
+ require 'crystal_goodies/string/extensions'
45
+ require 'crystal_goodies/array/extensions'
46
+ require 'crystal_goodies/enumerable/extensions'
47
+ ```
48
+
49
+ ### Object
50
+
51
+ #### in?(*collection) -> true, false
52
+
53
+ Returns `true` if `self` is included in the *collection* argument.
54
+
55
+ ```
56
+ 10.in?(0..100) # => true
57
+ 10.in?(0, 1, 10) # => true
58
+ 10.in?(:foo, :bar) # => false
59
+ ```
60
+
61
+ ### Integer
62
+
63
+ #### divisible_by?(num) -> true, false
64
+
65
+ Returns `true` if `self` is divisible by *num*.
66
+
67
+ ```
68
+ 6.divisible_by? 3 # => true
69
+ 6.divisible_by? 2 # => true
70
+ 5.divisible_by? 3 # => false
71
+ ```
72
+
73
+ #### to(limit) { |i| ... } -> self
74
+
75
+ Call `upto` or `downto` depend on the *limit*.
76
+
77
+ ### String
78
+
79
+ #### camelcase(options, lower: false) -> String
80
+
81
+ Converts underscores to camelcase boundaries.
82
+
83
+ If *lower* is true, lower camelcase will be returned (the first letter is downcased).
84
+
85
+ ```
86
+ "eiffel_tower".camelcase # => "EiffelTower"
87
+ "empire_state_building".camelcase(lower: true) # => "empireStateBuilding"
88
+ ```
89
+
90
+ #### titleize(options) -> String
91
+
92
+ Returns a new `String` with the first letter after any space converted to uppercase and every
93
+ other letter converted to lowercase.
94
+
95
+ ```
96
+ "hEllO tAb\tworld".titleize # => "Hello Tab\tWorld"
97
+ " spaces before".titleize # => " Spaces Before"
98
+ "x-men: the last stand".titleize # => "X-men: The Last Stand"
99
+ ```
100
+
101
+ #### underscore(options) -> String
102
+
103
+ Converts camelcase boundaries to underscores.
104
+
105
+ ```
106
+ "DoesWhatItSaysOnTheTin".underscore # => "does_what_it_says_on_the_tin"
107
+ "PartyInTheUSA".underscore # => "party_in_the_usa"
108
+ "HTTP_CLIENT".underscore # => "http_client"
109
+ "3.14IsPi".underscore # => "3.14_is_pi"
110
+ ```
111
+
112
+ #### dasherize(options) -> String
113
+
114
+ Converts camelcase boundaries to kebabcase.
115
+
116
+ ```
117
+ "DoesWhatItSaysOnTheTin".dasherize # => "does-what-it-says-on-the-tin"
118
+ "PartyInTheUSA".dasherize # => "party-in-the-usa"
119
+ "HTTP_CLIENT".dasherize # => "http-client"
120
+ "3.14IsPi".dasherize # => "3.14-is-pi"
121
+ ```
122
+
123
+ #### blank? -> true, false
124
+
125
+ Returns `true` if this string consists exclusively of unicode whitespace.
126
+
127
+ ```
128
+ "".blank? # => true
129
+ " ".blank? # => true
130
+ " a ".blank? # => false
131
+ ```
132
+
133
+ #### presence -> self, nil
134
+
135
+ Returns `self` unless `#blank?` is `true` in which case it returns `nil`.
136
+
137
+ ```
138
+ "a".presence # => "a"
139
+ "".presence # => nil
140
+ " ".presence # => nil
141
+ " a ".presence # => " a "
142
+ ```
143
+
144
+ #### delete_at(...) -> String
145
+
146
+ Returns a new string that results from deleting characters with `slice`.
147
+
148
+ #### to(limit, exclusive = false) -> self
149
+
150
+ Call `upto` or `downto` depend on the *limit*.
151
+
152
+ ### Array
153
+
154
+ #### skip(count) -> Array
155
+
156
+ Returns an `Array` with the first *count* elements removed
157
+ from the original array.
158
+
159
+ If *count* is bigger than the number of elements in the array, returns an empty array.
160
+
161
+ ```
162
+ [1, 2, 3, 4, 5, 6].skip(3) # => [4, 5, 6]
163
+ ```
164
+
165
+ #### truncate(...) -> elements
166
+
167
+ Removes all elements except the *count* or less (if there aren't enough)
168
+ elements starting at the given *start* index. Returns `self`.
169
+
170
+ Negative values of *start* count from the end of the array.
171
+
172
+ Raises `IndexError` if the *start* index is out of range.
173
+
174
+ Raises `ArgumentError` if *count* is negative.
175
+
176
+ ```
177
+ a = [0, 1, 4, 9, 16, 25]
178
+ a.truncate(2, 3) # => [4, 9, 16]
179
+ a # => [4, 9, 16]
180
+ ```
181
+
182
+ Or removes all elements except those within the given *range*. Returns `self`.
183
+
184
+ ```
185
+ a = [0, 1, 4, 9, 16, 25]
186
+ a.truncate(1..-3) # => [1, 4, 9]
187
+ a # => [1, 4, 9]
188
+ ```
189
+
190
+ ### Enumerable
191
+
192
+ #### empty? -> true, false
193
+
194
+ Returns `true` if `self` is empty, `false` otherwise.
195
+
196
+ ```
197
+ [].empty? # => true
198
+ [1].empty? # => false
199
+ ```
200
+
201
+ #### compact_map { ... } -> Array
202
+
203
+ Returns an `Array` with the results of running the block against each element
204
+ of the collection, removing `nil` values.
205
+
206
+ ```
207
+ ["Alice", "Bob"].map { |name| name.match(/^A./) } # => [#<MatchData "Al">, nil]
208
+ ["Alice", "Bob"].compact_map { |name| name.match(/^A./) } # => [#<MatchData "Al">]
209
+ ```
210
+
211
+ #### in_groups_of(size, filled_up_with = nil) -> Array
212
+
213
+ Returns an `Array` with chunks in the given size, eventually filled up
214
+ with given value or `nil`.
215
+
216
+ ```
217
+ [1, 2, 3].in_groups_of(2, 0) # => [[1, 2], [3, 0]]
218
+ [1, 2, 3].in_groups_of(2) # => [[1, 2], [3, nil]]
219
+ ```
220
+
221
+ #### skip_while { ... } -> Array
222
+
223
+ Skips elements up to, but not including, the first element for which
224
+ the block is falsey, and returns an `Array`
225
+ containing the remaining elements.
226
+
227
+ ```
228
+ [1, 2, 3, 4, 5, 0].skip_while { _1 < 3 } # => [3, 4, 5, 0]
229
+ ```
230
+
231
+ #### index_by { ... } -> Hash
232
+
233
+ Converts an `Enumerable` to a `Hash` by using the value returned by the block
234
+ as the hash key.
235
+ Be aware, if two elements return the same value as a key one will override
236
+ the other. If you want to keep all values, then you should probably use
237
+ `group_by` instead.
238
+
239
+ ```
240
+ ["Anna", "Ary", "Alice"].index_by(&:size)
241
+ # => {4 => "Anna", 3 => "Ary", 5 => "Alice"}
242
+ ["Anna", "Ary", "Alice", "Bob"].index_by(&:size)
243
+ # => {4 => "Anna", 3 => "Bob", 5 => "Alice"}
244
+ ```
245
+
246
+ #### tally_by(hash = {}) { ... } -> Hash
247
+
248
+ Tallies the collection. Accepts a *hash* to count occurrences.
249
+ The value corresponding to each element must be an integer.
250
+ Returns *hash* where the keys are the
251
+ elements and the values are numbers of elements in the collection
252
+ that correspond to the key after transformation by the given block.
253
+
254
+ ```
255
+ hash = {}
256
+ words = ["Crystal", "Ruby"]
257
+ words.each { |word| word.chars.tally_by(hash, &:downcase) }
258
+ hash # => {"c" => 1, "r" => 2, "y" => 2, "s" => 1, "t" => 1, "a" => 1, "l" => 1, "u" => 1, "b" => 1}
259
+ ```
260
+
261
+ #### min_of? { ... } -> min_element
262
+
263
+ Returns the element for which the passed block returns with the maximum value.
264
+
265
+ It compares using `>` so the block must return a type that supports that method
266
+
267
+ ```
268
+ ["Alice", "Bob"].max_by(&:size) # => "Alice"
269
+ ```
270
+
271
+ Return `nil` if the collection is empty.
272
+
273
+ #### max_of? { ... } -> max_element
274
+
275
+ Returns the element for which the passed block returns with the minimum value.
276
+
277
+ It compares using `<` so the block must return a type that supports that method
278
+
279
+ ```
280
+ ["Alice", "Bob"].min_by(&:size) # => "Bob"
281
+ ```
282
+
283
+ Return `nil` if the collection is empty.
284
+
285
+ #### minmax_of? { ... } -> [min_element, max_element]
286
+
287
+ Returns a `Array` with both the minimum and maximum values according to the passed block.
288
+
289
+ ```
290
+ ["Alice", "Bob", "Carl"].minmax_by(&:size) # => ["Bob", "Alice"]
291
+ ```
292
+
293
+ Return `[nil, nil]` if the collection is empty.
29
294
 
30
295
  ## 💌 Credits
31
296
 
32
297
  - [**Crystal**](https://crystal-lang.org) by [it's contributors](https://github.com/crystal-lang/crystal/graphs/contributors)
298
+ - [**Ruby on Rails**](https://rubyonrails.org) by [it's contributors](https://github.com/rails/rails/graphs/contributors)
33
299
 
34
300
  <a href="https://codeberg.org/NNB"><img width="100%" src="https://capsule-render.vercel.app/api?type=waving&section=footer&color=DC2626&fontColor=FEF2F2&height=128&desc=Made%20with%20%26lt;3%20by%20NNB&descAlignY=80" /></a>
@@ -21,7 +21,6 @@ module CrystalGoodies
21
21
  # ["Alice", "Bob"].compact_map { |name| name.match(/^A./) } # => [#<MatchData "Al">]
22
22
  # ```
23
23
  def compact_map(&)
24
- # FIXME
25
24
  map(&).compact
26
25
  end
27
26
 
@@ -2,13 +2,13 @@
2
2
 
3
3
  module CrystalGoodies
4
4
  class Object
5
- # Returns `true` if `self` is included in the *collection* argument.
6
- #
7
- # ```
8
- # 10.in?(0..100) # => true
9
- # 10.in?(0, 1, 10) # => true
10
- # 10.in?(:foo, :bar) # => false
11
- # ```
5
+ # Returns `true` if `self` is included in the *collection* argument.
6
+ #
7
+ # ```
8
+ # 10.in?(0..100) # => true
9
+ # 10.in?(0, 1, 10) # => true
10
+ # 10.in?(:foo, :bar) # => false
11
+ # ```
12
12
  def in?(*collection)
13
13
  (collection.one? ? collection.first : collection).include? self
14
14
  end
@@ -61,78 +61,9 @@ module CrystalGoodies
61
61
  # "3.14IsPi".underscore # => "3.14_is_pi"
62
62
  # ```
63
63
  def underscore(*options)
64
- <<-FIXME
65
-
66
- string = ''
67
- first = true
68
- last_is_downcase = false
69
- last_is_upcase = false
70
- last_is_digit = false
71
- mem = nil
72
-
73
- each_char do |char|
74
- if options.ascii?
75
- digit = char.ascii_number?
76
- downcase = digit || char.ascii_lowercase?
77
- upcase = char.ascii_uppercase?
78
- else
79
- digit = char.number?
80
- downcase = digit || char.lowercase?
81
- upcase = char.uppercase?
82
- end
83
-
84
- if first
85
- char.downcase(options) { |c| string << c }
86
- elsif last_is_downcase && upcase
87
- if mem
88
- # This is the case of A1Bcd, we need to put 'mem' (not to need to convert as downcase
89
- # ^
90
- # because 'mem' is digit surely) before putting this char as downcase.
91
- string << mem
92
- mem = nil
93
- end
94
- # This is the case of AbcDe, we need to put an underscore before the 'D'
95
- # ^
96
- string << '_'
97
- char.downcase(options) { |c| string << c }
98
- elsif (last_is_upcase || last_is_digit) && (upcase || digit)
99
- # This is the case of 1) A1Bcd, 2) A1BCd or 3) A1B_cd:if the next char is upcase (case 1) we need
100
- # ^ ^ ^
101
- # 1) we need to append this char as downcase
102
- # 2) we need to append an underscore and then the char as downcase, so we save this char
103
- # in 'mem' and decide later
104
- # 3) we need to append this char as downcase and then a single underscore
105
- if mem
106
- # case 2
107
- mem.downcase(options) { |c| string << c }
108
- end
109
- mem = char
110
- else
111
- if mem
112
- if char == '_'
113
- # case 3
114
- elsif last_is_upcase && downcase
115
- # case 1
116
- string << '_'
117
- end
118
- mem.downcase(options) { |c| string << c }
119
- mem = nil
120
- end
121
-
122
- char.downcase(options) { |c| string << c }
123
- end
124
-
125
- last_is_downcase = downcase
126
- last_is_upcase = upcase
127
- last_is_digit = digit
128
- first = false
129
- end
130
-
131
- mem&.downcase(options) { |c| string << c }
132
-
133
- FIXME
134
-
135
- self
64
+ gsub(/([A-Z])(?=[A-Z][a-z])|([a-z\d])(?=[A-Z])/) { (_1 || _2) << '_' }
65
+ .tr('-', '_')
66
+ .downcase(*options)
136
67
  end
137
68
 
138
69
  # Converts camelcase boundaries to kebabcase.
@@ -143,8 +74,8 @@ module CrystalGoodies
143
74
  # "HTTP_CLIENT".dasherize # => "http-client"
144
75
  # "3.14IsPi".dasherize # => "3.14-is-pi"
145
76
  # ```
146
- def dasherize
147
- underscore.tr('_', '-')
77
+ def dasherize(*options)
78
+ underscore(*options).tr('_', '-')
148
79
  end
149
80
 
150
81
  # Returns `true` if this string consists exclusively of unicode whitespace.
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module CrystalGoodies
4
- VERSION = '1.0.0'
4
+ VERSION = '1.0.2'
5
5
  end
data/sig/enumerable.rbs CHANGED
@@ -2,8 +2,7 @@ module CrystalGoodies
2
2
  module Enumerable
3
3
  def empty?: () -> bool
4
4
 
5
- def compact_map: () -> Enumerator
6
- | () { () -> void } -> Array
5
+ def compact_map: () { () -> void } -> Array
7
6
 
8
7
  def in_groups_of: (Integer size, ?untyped? filled_up_with) -> Array
9
8
 
metadata CHANGED
@@ -1,16 +1,16 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: crystal_goodies
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - NNB
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-08-15 00:00:00.000000000 Z
11
+ date: 2023-08-16 00:00:00.000000000 Z
12
12
  dependencies: []
13
- description: Class's methods port from Crystal.
13
+ description: Class's methods convenient for scripting port from Crystal.
14
14
  email:
15
15
  - nnbnh@protonmail.com
16
16
  executables: []