code-ruby 4.0.3 → 5.0.1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b1a5c3d96bf160e16bae12219941a66d83d1a4e34741d4973538b4b51a67cfbb
4
- data.tar.gz: 42c77b63bcae3183bf9e9fa7c521b04a845684040d078f653ed67c07a655aa1c
3
+ metadata.gz: f87766e8837d19a0644c29508a53840df32e22e5b46802d08e135ea2dd9ad873
4
+ data.tar.gz: ec59cc05b2c71146e356bb86ec51fb08001538a3274a67421cdaa2f3f1de8d66
5
5
  SHA512:
6
- metadata.gz: a840d30c8b19f56834e7e296e5ecb6a93a9b3d5f00f1456604012a64e4820d425dd94f7206a4189dc572f3bde05679084db4af3b568e19ac0e3c8d5a21e7587b
7
- data.tar.gz: 248c1a70da0e0825c62373dbca46a10b66cb4e95a0257a0db1108fd2d137a8b6a7ffeaec9466b7c7ba7815418665e5808ce1c62dcf05cace010e790a916a5256
6
+ metadata.gz: 56a77245fcc70a40ce249348540a936d814e1894b78d67bfab3d878ac0f7576c43be6d50433a8b3251fd90cac41656f36a39b8b87ca643aec1598926f4c03291
7
+ data.tar.gz: 5b841dcfdeb008bbf8fc80e7e6cf538c64a02e97f1aabe7271e94df76cbf480cdb575b87ea120632cfacdbd645d765c1eaba1a23d852d34f51ef5d2b8b8c65db
data/VERSION CHANGED
@@ -1 +1 @@
1
- 4.0.3
1
+ 5.0.1
@@ -5,19 +5,19 @@ class Code
5
5
  module Shared
6
6
  attr_accessor :raw, :functions
7
7
 
8
- COMPOUND_ASSIGNMENT_OPERATORS = %w[
9
- +=
10
- -=
11
- *=
12
- /=
13
- %=
14
- <<=
15
- >>=
16
- &=
17
- |=
18
- ^=
19
- ||=
20
- &&=
8
+ COMPOUND_ASSIGNMENT_OPERATORS = [
9
+ "+=",
10
+ "-=",
11
+ "*=",
12
+ "/=",
13
+ "%=",
14
+ "<<=",
15
+ ">>=",
16
+ "&=",
17
+ "|=",
18
+ "^=",
19
+ "||=",
20
+ "&&="
21
21
  ].freeze
22
22
  SHARED_OPERATORS = %w[
23
23
  documentation
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Regexp
4
+ def to_code
5
+ Code::Object::Regex.new(self)
6
+ end
7
+ end
@@ -1541,10 +1541,12 @@ class Code
1541
1541
 
1542
1542
  def code_to_precision(precision = nil)
1543
1543
  code_precision = precision.to_code
1544
- code_precision =
1545
- Integer.new(
1546
- raw.to_s("F").delete(".-").length
1547
- ) if code_precision.nothing?
1544
+ if code_precision.nothing?
1545
+ code_precision =
1546
+ Integer.new(
1547
+ raw.to_s("F").delete(".-").length
1548
+ )
1549
+ end
1548
1550
 
1549
1551
  String.new(format("%.#{code_precision.raw}g", raw))
1550
1552
  end
@@ -227,6 +227,16 @@ class Code
227
227
  "returns the Parameter class when called without arguments, otherwise calls Parameter.new.",
228
228
  examples: %w[Parameter Parameter.new Parameter.new(nothing)]
229
229
  },
230
+ "Regex" => {
231
+ name: "Regex",
232
+ description:
233
+ "returns the Regex class when called without arguments, otherwise calls Regex.new.",
234
+ examples: [
235
+ "Regex",
236
+ "Regex.new(\"a|b|c\")",
237
+ "Regex(\"^hello\", ignore_case: true)"
238
+ ]
239
+ },
230
240
  "Range" => {
231
241
  name: "Range",
232
242
  description:
@@ -417,6 +427,7 @@ class Code
417
427
  "Number" => Number,
418
428
  "Object" => Object,
419
429
  "Parameter" => Parameter,
430
+ "Regex" => Regex,
420
431
  "Range" => Range,
421
432
  "Smtp" => Smtp,
422
433
  "String" => String,
@@ -550,6 +561,13 @@ class Code
550
561
  else
551
562
  Class.new(Range)
552
563
  end
564
+ when "Regex"
565
+ sig(args) { Object.repeat }
566
+ if code_arguments.any?
567
+ Regex.new(*code_arguments.raw)
568
+ else
569
+ Class.new(Regex)
570
+ end
553
571
  when "String"
554
572
  sig(args) { Object.repeat }
555
573
  if code_arguments.any?
@@ -724,6 +724,24 @@ class Code
724
724
  "[].filter((x) => { x })"
725
725
  ]
726
726
  },
727
+ "grep" => {
728
+ name: "grep",
729
+ description: "returns string items matched by a regex.",
730
+ examples: [
731
+ "[\"ant\", \"bat\", \"cat\"].grep(Regex.new(\"a\"))",
732
+ "[\"ant\", \"bat\"].grep(Regex.new(\"^b\"))",
733
+ "[\"ant\", \"bat\"].grep(Regex.new(\"z\"))"
734
+ ]
735
+ },
736
+ "grep_not" => {
737
+ name: "grep_not",
738
+ description: "returns string items not matched by a regex.",
739
+ examples: [
740
+ "[\"ant\", \"bat\", \"cat\"].grep_not(Regex.new(\"a\"))",
741
+ "[\"ant\", \"bat\"].grep_not(Regex.new(\"^b\"))",
742
+ "[\"ant\", \"bat\"].grep_not(Regex.new(\"z\"))"
743
+ ]
744
+ },
727
745
  "select!" => {
728
746
  name: "select!",
729
747
  description:
@@ -3218,6 +3236,12 @@ class Code
3218
3236
  when "select", "filter"
3219
3237
  sig(args) { (Function | Class).maybe }
3220
3238
  code_select(code_value, **globals)
3239
+ when "grep"
3240
+ sig(args) { [Regex, (Function | Class).maybe] }
3241
+ code_grep(*code_arguments.raw, **globals)
3242
+ when "grep_not"
3243
+ sig(args) { [Regex, (Function | Class).maybe] }
3244
+ code_grep_not(*code_arguments.raw, **globals)
3221
3245
  when "select!", "filter!"
3222
3246
  sig(args) { (Function | Class).maybe }
3223
3247
  code_select!(code_value, **globals)
@@ -4889,6 +4913,62 @@ class Code
4889
4913
  e.code_value
4890
4914
  end
4891
4915
 
4916
+ def code_grep(regex, argument = nil, **globals)
4917
+ code_regex = regex.to_code
4918
+ code_argument = argument.to_code
4919
+ results = []
4920
+
4921
+ raw.each.with_index do |code_element, index|
4922
+ next unless code_element.is_a?(String) &&
4923
+ code_regex.raw.match?(code_element.raw)
4924
+
4925
+ results << if code_argument.is_a?(Function)
4926
+ code_argument.call(
4927
+ arguments: List.new([code_element, Integer.new(index), self]),
4928
+ **globals
4929
+ )
4930
+ elsif code_argument.is_a?(Class)
4931
+ code_argument.raw.new(code_element)
4932
+ else
4933
+ code_element
4934
+ end
4935
+ rescue Error::Next => e
4936
+ results << e.code_value
4937
+ end
4938
+
4939
+ List.new(results)
4940
+ rescue Error::Break => e
4941
+ e.code_value
4942
+ end
4943
+
4944
+ def code_grep_not(regex, argument = nil, **globals)
4945
+ code_regex = regex.to_code
4946
+ code_argument = argument.to_code
4947
+ results = []
4948
+
4949
+ raw.each.with_index do |code_element, index|
4950
+ next if code_element.is_a?(String) &&
4951
+ code_regex.raw.match?(code_element.raw)
4952
+
4953
+ results << if code_argument.is_a?(Function)
4954
+ code_argument.call(
4955
+ arguments: List.new([code_element, Integer.new(index), self]),
4956
+ **globals
4957
+ )
4958
+ elsif code_argument.is_a?(Class)
4959
+ code_argument.raw.new(code_element)
4960
+ else
4961
+ code_element
4962
+ end
4963
+ rescue Error::Next => e
4964
+ results << e.code_value
4965
+ end
4966
+
4967
+ List.new(results)
4968
+ rescue Error::Break => e
4969
+ e.code_value
4970
+ end
4971
+
4892
4972
  def code_reject(argument = nil, **globals)
4893
4973
  code_argument = argument.to_code
4894
4974
 
@@ -5063,7 +5143,7 @@ class Code
5063
5143
  def code_deep_duplicate
5064
5144
  duplicate = List.new
5065
5145
  duplicate.raw.concat(
5066
- raw.map { |value| value.code_deep_duplicate }
5146
+ raw.map(&:code_deep_duplicate)
5067
5147
  )
5068
5148
  duplicate
5069
5149
  end
@@ -660,12 +660,10 @@ class Code
660
660
  else
661
661
  code_element.code_less_or_equal(code_right)
662
662
  end
663
+ elsif exclude_end?
664
+ code_element.code_greater(code_right)
663
665
  else
664
- if exclude_end?
665
- code_element.code_greater(code_right)
666
- else
667
- code_element.code_greater_or_equal(code_right)
668
- end
666
+ code_element.code_greater_or_equal(code_right)
669
667
  end
670
668
 
671
669
  break unless comparison.truthy?
@@ -0,0 +1,234 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Code
4
+ class Object
5
+ class Regex < Object
6
+ CLASS_DOCUMENTATION = {
7
+ name: "Regex",
8
+ description:
9
+ "represents a regular expression pattern with explicit matching options.",
10
+ examples: [
11
+ "Regex",
12
+ "Regex.new(\"a|b|c\")",
13
+ "Regex.new(\"^hello\", ignore_case: true)"
14
+ ]
15
+ }.freeze
16
+ INSTANCE_FUNCTIONS = {
17
+ "match?" => {
18
+ name: "match?",
19
+ description: "returns whether the regex matches a string.",
20
+ examples: [
21
+ "Regex.new(\"a|b|c\").match?(\"b\")",
22
+ "Regex.new(\"^hello\").match?(\"hello world\")",
23
+ "Regex.new(\"^hello\").match?(\"say hello\")"
24
+ ]
25
+ },
26
+ "source" => {
27
+ name: "source",
28
+ description: "returns the regex pattern source.",
29
+ examples: [
30
+ "Regex.new(\"a|b|c\").source",
31
+ "Regex.new(\"^hello\").source",
32
+ "Regex.new(\"hello\", ignore_case: true).source"
33
+ ]
34
+ },
35
+ "options" => {
36
+ name: "options",
37
+ description: "returns the enabled regex options.",
38
+ examples: [
39
+ "Regex.new(\"hello\").options",
40
+ "Regex.new(\"hello\", ignore_case: true).options.ignore_case",
41
+ "Regex.new(\"hello\", multiple_lines: true).options.multiple_lines"
42
+ ]
43
+ },
44
+ "ignore_case?" => {
45
+ name: "ignore_case?",
46
+ description: "returns whether the regex ignores case.",
47
+ examples: [
48
+ "Regex.new(\"hello\").ignore_case?",
49
+ "Regex.new(\"hello\", ignore_case: true).ignore_case?",
50
+ "Regex.new(\"hello\", ignore_case: false).ignore_case?"
51
+ ]
52
+ },
53
+ "extended?" => {
54
+ name: "extended?",
55
+ description: "returns whether the regex ignores whitespace and comments.",
56
+ examples: [
57
+ "Regex.new(\"hello\").extended?",
58
+ "Regex.new(\"hello\", extended: true).extended?",
59
+ "Regex.new(\"hello\", extended: false).extended?"
60
+ ]
61
+ },
62
+ "multiple_lines?" => {
63
+ name: "multiple_lines?",
64
+ description: "returns whether the regex matches across multiple lines.",
65
+ examples: [
66
+ "Regex.new(\"hello\").multiple_lines?",
67
+ "Regex.new(\"hello\", multiple_lines: true).multiple_lines?",
68
+ "Regex.new(\"hello\", multiple_lines: false).multiple_lines?"
69
+ ]
70
+ },
71
+ "fixed_encoding?" => {
72
+ name: "fixed_encoding?",
73
+ description: "returns whether the regex has fixed encoding.",
74
+ examples: [
75
+ "Regex.new(\"hello\").fixed_encoding?",
76
+ "Regex.new(\"hello\", fixed_encoding: true).fixed_encoding?",
77
+ "Regex.new(\"hello\", fixed_encoding: false).fixed_encoding?"
78
+ ]
79
+ },
80
+ "no_encoding?" => {
81
+ name: "no_encoding?",
82
+ description: "returns whether the regex has no encoding.",
83
+ examples: [
84
+ "Regex.new(\"hello\").no_encoding?",
85
+ "Regex.new(\"hello\", no_encoding: true).no_encoding?",
86
+ "Regex.new(\"hello\", no_encoding: false).no_encoding?"
87
+ ]
88
+ }
89
+ }.freeze
90
+ OPTION_FLAGS = {
91
+ "ignore_case" => ::Regexp::IGNORECASE,
92
+ "extended" => ::Regexp::EXTENDED,
93
+ "multiple_lines" => ::Regexp::MULTILINE,
94
+ "fixed_encoding" => ::Regexp::FIXEDENCODING,
95
+ "no_encoding" => ::Regexp::NOENCODING
96
+ }.freeze
97
+
98
+ def self.function_documentation(scope)
99
+ return INSTANCE_FUNCTIONS if scope == :instance
100
+
101
+ {}
102
+ end
103
+
104
+ def initialize(*args, **kargs, &_block)
105
+ raise Error, "Regex.new: pattern is required" if args.empty?
106
+ raise Error, "Regex.new: expected 1-2 arguments" if args.size > 2
107
+
108
+ pattern = args.first
109
+ option_values = {}
110
+
111
+ if args[1]
112
+ case args[1]
113
+ when Dictionary
114
+ args[1].raw.each do |key, value|
115
+ option_values[key.to_s] =
116
+ value.is_an?(Object) ? value.truthy? : !!value
117
+ end
118
+ when ::Hash
119
+ args[1].each do |key, value|
120
+ option_values[key.to_s] =
121
+ value.is_an?(Object) ? value.truthy? : !!value
122
+ end
123
+ else
124
+ raise Error, "Regex.new: options must be a dictionary"
125
+ end
126
+ end
127
+
128
+ kargs.each do |key, value|
129
+ option_values[key.to_s] =
130
+ value.is_an?(Object) ? value.truthy? : !!value
131
+ end
132
+
133
+ options =
134
+ option_values.reduce(0) do |flags, (name, enabled)|
135
+ flag = OPTION_FLAGS[name]
136
+ raise Error, "unknown regex option: #{name}" unless flag
137
+
138
+ enabled ? flags | flag : flags
139
+ end
140
+
141
+ self.raw =
142
+ if pattern.is_a?(Regex)
143
+ ::Regexp.new(pattern.raw.source, pattern.raw.options | options)
144
+ elsif pattern.is_a?(::Regexp)
145
+ ::Regexp.new(pattern.source, pattern.options | options)
146
+ else
147
+ ::Regexp.new(pattern.to_s, options)
148
+ end
149
+ rescue ::RegexpError => e
150
+ raise Error, "invalid regex: #{e.message}"
151
+ end
152
+
153
+ def call(**args)
154
+ code_operator = args.fetch(:operator, nil).to_code
155
+ code_arguments = args.fetch(:arguments, List.new).to_code
156
+ code_value = code_arguments.code_first
157
+
158
+ case code_operator.to_s
159
+ when "match?"
160
+ sig(args) { String }
161
+ code_match?(code_value)
162
+ when "source"
163
+ sig(args)
164
+ code_source
165
+ when "options"
166
+ sig(args)
167
+ code_options
168
+ when "ignore_case?"
169
+ sig(args)
170
+ code_ignore_case?
171
+ when "extended?"
172
+ sig(args)
173
+ code_extended?
174
+ when "multiple_lines?"
175
+ sig(args)
176
+ code_multiple_lines?
177
+ when "fixed_encoding?"
178
+ sig(args)
179
+ code_fixed_encoding?
180
+ when "no_encoding?"
181
+ sig(args)
182
+ code_no_encoding?
183
+ else
184
+ super
185
+ end
186
+ end
187
+
188
+ def code_match?(string)
189
+ Boolean.new(raw.match?(string.to_s))
190
+ end
191
+
192
+ def code_source
193
+ String.new(raw.source)
194
+ end
195
+
196
+ def code_options
197
+ Dictionary.new(
198
+ OPTION_FLAGS.transform_values { |flag| (raw.options & flag) == flag }
199
+ )
200
+ end
201
+
202
+ def code_ignore_case?
203
+ Boolean.new((raw.options & ::Regexp::IGNORECASE) == ::Regexp::IGNORECASE)
204
+ end
205
+
206
+ def code_extended?
207
+ Boolean.new((raw.options & ::Regexp::EXTENDED) == ::Regexp::EXTENDED)
208
+ end
209
+
210
+ def code_multiple_lines?
211
+ Boolean.new((raw.options & ::Regexp::MULTILINE) == ::Regexp::MULTILINE)
212
+ end
213
+
214
+ def code_fixed_encoding?
215
+ Boolean.new(
216
+ (raw.options & ::Regexp::FIXEDENCODING) == ::Regexp::FIXEDENCODING
217
+ )
218
+ end
219
+
220
+ def code_no_encoding?
221
+ Boolean.new((raw.options & ::Regexp::NOENCODING) == ::Regexp::NOENCODING)
222
+ end
223
+
224
+ def code_to_string
225
+ code_source
226
+ end
227
+
228
+ def code_inspect
229
+ String.new(raw.inspect)
230
+ end
231
+
232
+ end
233
+ end
234
+ end
@@ -70,6 +70,24 @@ class Code
70
70
  "\":name\".member?(\":\")"
71
71
  ]
72
72
  },
73
+ "match?" => {
74
+ name: "match?",
75
+ description: "returns whether the string matches a regex.",
76
+ examples: [
77
+ "\"hello\".match?(Regex.new(\"ell\"))",
78
+ "\"hello\".match?(Regex.new(\"^he\"))",
79
+ "\"hello\".match?(Regex.new(\"world\"))"
80
+ ]
81
+ },
82
+ "matches?" => {
83
+ name: "matches?",
84
+ description: "returns whether the string matches a regex.",
85
+ examples: [
86
+ "\"hello\".matches?(Regex.new(\"ell\"))",
87
+ "\"hello\".matches?(Regex.new(\"^he\"))",
88
+ "\"hello\".matches?(Regex.new(\"world\"))"
89
+ ]
90
+ },
73
91
  "starts_with?" => {
74
92
  name: "starts_with?",
75
93
  description: "returns whether the string starts with another string.",
@@ -273,10 +291,10 @@ class Code
273
291
  },
274
292
  "index" => {
275
293
  name: "index",
276
- description: "returns the index of a matching substring.",
294
+ description: "returns the index of a matching substring or regex.",
277
295
  examples: [
278
296
  "\"hello\".index(\"l\")",
279
- "\"hello\".index(\"x\")",
297
+ "\"hello\".index(Regex.new(\"l+\"))",
280
298
  "\"banana\".index(\"na\")"
281
299
  ]
282
300
  },
@@ -297,10 +315,11 @@ class Code
297
315
  },
298
316
  "right_index" => {
299
317
  name: "right_index",
300
- description: "returns the last index of a matching substring.",
318
+ description:
319
+ "returns the last index of a matching substring or regex.",
301
320
  examples: [
302
321
  "\"hello\".right_index(\"l\")",
303
- "\"hello\".right_index(\"x\")",
322
+ "\"hello\".right_index(Regex.new(\"l\"))",
304
323
  "\"banana\".right_index(\"na\")"
305
324
  ]
306
325
  },
@@ -527,7 +546,16 @@ class Code
527
546
  examples: [
528
547
  "\"a,b\".split(\",\")",
529
548
  "\"a b\".split",
530
- "\"a--b\".split(\"--\")"
549
+ "\"a,b;c\".split(Regex.new(\"[,;]\"))"
550
+ ]
551
+ },
552
+ "scan" => {
553
+ name: "scan",
554
+ description: "returns every regex match in the string.",
555
+ examples: [
556
+ "\"a1 b22\".scan(Regex.new(\"[0-9]+\"))",
557
+ "\"abc\".scan(Regex.new(\"[a-z]\"))",
558
+ "\"abc\".scan(Regex.new(\"x\"))"
531
559
  ]
532
560
  },
533
561
  "words" => {
@@ -583,6 +611,9 @@ class Code
583
611
  when "include?", "member?"
584
612
  sig(args) { String }
585
613
  code_include?(code_value)
614
+ when "match?", "matches?"
615
+ sig(args) { Regex }
616
+ code_match?(code_value)
586
617
  when "starts_with?"
587
618
  sig(args) { String }
588
619
  code_starts_with?(code_value)
@@ -659,7 +690,7 @@ class Code
659
690
  sig(args) { Integer.maybe }
660
691
  code_first(code_value)
661
692
  when "index"
662
- sig(args) { String }
693
+ sig(args) { String | Regex }
663
694
  code_index(code_value)
664
695
  when "last"
665
696
  sig(args) { Integer.maybe }
@@ -671,7 +702,7 @@ class Code
671
702
  sig(args)
672
703
  code_reverse
673
704
  when "right_index"
674
- sig(args) { String }
705
+ sig(args) { String | Regex }
675
706
  code_right_index(code_value)
676
707
  when "parameterize"
677
708
  sig(args)
@@ -683,22 +714,22 @@ class Code
683
714
  sig(args) { String.repeat }
684
715
  code_squeeze(*code_arguments.raw)
685
716
  when "substitute"
686
- sig(args) { [String, String.maybe] }
717
+ sig(args) { [String | Regex, String.maybe] }
687
718
  code_substitute(*code_arguments.raw)
688
719
  when "substitute!"
689
- sig(args) { [String, String.maybe] }
720
+ sig(args) { [String | Regex, String.maybe] }
690
721
  code_substitute!(*code_arguments.raw)
691
722
  when "substitute_all"
692
- sig(args) { [String, String.maybe] }
723
+ sig(args) { [String | Regex, String.maybe] }
693
724
  code_substitute_all(*code_arguments.raw)
694
725
  when "substitute_all!"
695
- sig(args) { [String, String.maybe] }
726
+ sig(args) { [String | Regex, String.maybe] }
696
727
  code_substitute_all!(*code_arguments.raw)
697
728
  when "substitute_once"
698
- sig(args) { [String, String.maybe] }
729
+ sig(args) { [String | Regex, String.maybe] }
699
730
  code_substitute_once(*code_arguments.raw)
700
731
  when "substitute_once!"
701
- sig(args) { [String, String.maybe] }
732
+ sig(args) { [String | Regex, String.maybe] }
702
733
  code_substitute_once!(*code_arguments.raw)
703
734
  when "swapcase"
704
735
  sig(args)
@@ -749,8 +780,11 @@ class Code
749
780
  sig(args) { [Integer.maybe, Integer.maybe] }
750
781
  code_substring(*code_arguments.raw)
751
782
  when "split"
752
- sig(args) { String.maybe }
783
+ sig(args) { (String | Regex).maybe }
753
784
  code_split(code_value)
785
+ when "scan"
786
+ sig(args) { Regex }
787
+ code_scan(code_value)
754
788
  when "words"
755
789
  sig(args)
756
790
  code_words
@@ -887,6 +921,11 @@ class Code
887
921
  Boolean.new(raw.include?(code_value.raw))
888
922
  end
889
923
 
924
+ def code_match?(value)
925
+ code_value = value.to_code
926
+ Boolean.new(code_value.raw.match?(raw))
927
+ end
928
+
890
929
  def code_index(value)
891
930
  code_value = value.to_code
892
931
  raw.index(code_value.raw).to_code
@@ -1000,8 +1039,9 @@ class Code
1000
1039
  def code_substitute_all(from = nil, to = nil)
1001
1040
  code_from = from.to_code
1002
1041
  code_to = to.to_code
1042
+ from_value = code_from.is_a?(Regex) ? code_from.raw : code_from.to_s
1003
1043
 
1004
- String.new(raw.gsub(code_from.to_s, code_to.to_s))
1044
+ String.new(raw.gsub(from_value, code_to.to_s))
1005
1045
  end
1006
1046
 
1007
1047
  def code_substitute_all!(from = nil, to = nil)
@@ -1012,8 +1052,9 @@ class Code
1012
1052
  def code_substitute_once(from = nil, to = nil)
1013
1053
  code_from = from.to_code
1014
1054
  code_to = to.to_code
1055
+ from_value = code_from.is_a?(Regex) ? code_from.raw : code_from.to_s
1015
1056
 
1016
- String.new(raw.sub(code_from.to_s, code_to.to_s))
1057
+ String.new(raw.sub(from_value, code_to.to_s))
1017
1058
  end
1018
1059
 
1019
1060
  def code_substitute_once!(from = nil, to = nil)
@@ -1132,10 +1173,22 @@ class Code
1132
1173
  if code_value.nothing?
1133
1174
  List.new(raw.split)
1134
1175
  else
1135
- List.new(raw.split(code_value.to_s))
1176
+ separator = code_value.is_a?(Regex) ? code_value.raw : code_value.to_s
1177
+
1178
+ List.new(raw.split(separator))
1136
1179
  end
1137
1180
  end
1138
1181
 
1182
+ def code_scan(value)
1183
+ code_value = value.to_code
1184
+
1185
+ List.new(
1186
+ raw.scan(code_value.raw).map do |match|
1187
+ match.is_a?(::Array) ? List.new(match) : String.new(match)
1188
+ end
1189
+ )
1190
+ end
1191
+
1139
1192
  def code_words
1140
1193
  List.new(raw.split)
1141
1194
  end
data/lib/code/parser.rb CHANGED
@@ -32,42 +32,43 @@ class Code
32
32
  while
33
33
  ].freeze
34
34
 
35
- MULTI_CHAR_OPERATORS = %w[
36
- &.
37
- &&
38
- &&=
39
- **
40
- *=
41
- +=
42
- -=
43
- ..
44
- ...
45
- /=
46
- ::
47
- <<=
48
- <<
49
- <=>
50
- <=
51
- ===
52
- ==
53
- =~
54
- >=
55
- >>=
56
- >>
57
- ||=
58
- ||
59
- |=
60
- !==
61
- !=
62
- !~
63
- %=
64
- ^=
65
- =>
35
+ MULTI_CHAR_OPERATORS = [
36
+ "&.",
37
+ "&&",
38
+ "&&=",
39
+ "**",
40
+ "*=",
41
+ "+=",
42
+ "-=",
43
+ "..",
44
+ "...",
45
+ "/=",
46
+ "::",
47
+ "<<=",
48
+ "<<",
49
+ "<=>",
50
+ "<=",
51
+ "===",
52
+ "==",
53
+ "=~",
54
+ ">=",
55
+ ">>=",
56
+ ">>",
57
+ "||=",
58
+ "||",
59
+ "|=",
60
+ "!==",
61
+ "!=",
62
+ "!~",
63
+ "%=",
64
+ "^=",
65
+ "=>"
66
66
  ].sort_by(&:length).reverse.freeze
67
67
  CONTINUATION_KEYWORDS = %w[or and rescue].freeze
68
68
  POSTFIX_CONTINUATIONS = %w[. :: &.].freeze
69
69
  HORIZONTAL_WHITESPACE = [" ", "\t"].freeze
70
70
  NEWLINE_CHARACTERS = ["\n", "\r"].freeze
71
+ QUOTE_CHARACTERS = ["'", '"'].freeze
71
72
  PUNCTUATION_CHARACTERS = %w[( ) [ ] { } , ? :].freeze
72
73
  OPERATOR_CHARACTERS = %w[. & | = ! ~ + - * / % < > ^ × ÷].freeze
73
74
  SUFFIX_PUNCTUATION = %w[! ?].freeze
@@ -1266,7 +1267,7 @@ class Code
1266
1267
  next
1267
1268
  end
1268
1269
 
1269
- if %w[' "].include?(char)
1270
+ if QUOTE_CHARACTERS.include?(char)
1270
1271
  quote = char
1271
1272
  elsif char == "#"
1272
1273
  while i < source.length && !NEWLINE_CHARACTERS.include?(source[i])
data/lib/code-ruby.rb CHANGED
@@ -33,6 +33,7 @@ require_relative "code/extensions/nil_class"
33
33
  require_relative "code/extensions/true_class"
34
34
  require_relative "code/extensions/false_class"
35
35
  require_relative "code/extensions/string"
36
+ require_relative "code/extensions/regexp"
36
37
  require_relative "code/extensions/symbol"
37
38
  require_relative "code/extensions/integer"
38
39
  require_relative "code/extensions/float"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: code-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.0.3
4
+ version: 5.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dorian Marié
@@ -15,7 +15,7 @@ dependencies:
15
15
  requirements:
16
16
  - - ">="
17
17
  - !ruby/object:Gem::Version
18
- version: '8.1'
18
+ version: 7.1.6
19
19
  - - "<"
20
20
  - !ruby/object:Gem::Version
21
21
  version: '9'
@@ -25,7 +25,7 @@ dependencies:
25
25
  requirements:
26
26
  - - ">="
27
27
  - !ruby/object:Gem::Version
28
- version: '8.1'
28
+ version: 7.1.6
29
29
  - - "<"
30
30
  - !ruby/object:Gem::Version
31
31
  version: '9'
@@ -35,7 +35,7 @@ dependencies:
35
35
  requirements:
36
36
  - - ">="
37
37
  - !ruby/object:Gem::Version
38
- version: '0.3'
38
+ version: 0.3.0
39
39
  - - "<"
40
40
  - !ruby/object:Gem::Version
41
41
  version: '1'
@@ -45,7 +45,7 @@ dependencies:
45
45
  requirements:
46
46
  - - ">="
47
47
  - !ruby/object:Gem::Version
48
- version: '0.3'
48
+ version: 0.3.0
49
49
  - - "<"
50
50
  - !ruby/object:Gem::Version
51
51
  version: '1'
@@ -55,7 +55,7 @@ dependencies:
55
55
  requirements:
56
56
  - - ">="
57
57
  - !ruby/object:Gem::Version
58
- version: '4.0'
58
+ version: 4.1.2
59
59
  - - "<"
60
60
  - !ruby/object:Gem::Version
61
61
  version: '5'
@@ -65,7 +65,7 @@ dependencies:
65
65
  requirements:
66
66
  - - ">="
67
67
  - !ruby/object:Gem::Version
68
- version: '4.0'
68
+ version: 4.1.2
69
69
  - - "<"
70
70
  - !ruby/object:Gem::Version
71
71
  version: '5'
@@ -75,7 +75,7 @@ dependencies:
75
75
  requirements:
76
76
  - - ">="
77
77
  - !ruby/object:Gem::Version
78
- version: '0.1'
78
+ version: 0.1.1
79
79
  - - "<"
80
80
  - !ruby/object:Gem::Version
81
81
  version: '1'
@@ -85,7 +85,7 @@ dependencies:
85
85
  requirements:
86
86
  - - ">="
87
87
  - !ruby/object:Gem::Version
88
- version: '0.1'
88
+ version: 0.1.1
89
89
  - - "<"
90
90
  - !ruby/object:Gem::Version
91
91
  version: '1'
@@ -95,7 +95,7 @@ dependencies:
95
95
  requirements:
96
96
  - - ">="
97
97
  - !ruby/object:Gem::Version
98
- version: '1.2'
98
+ version: 1.2.3
99
99
  - - "<"
100
100
  - !ruby/object:Gem::Version
101
101
  version: '2'
@@ -105,7 +105,7 @@ dependencies:
105
105
  requirements:
106
106
  - - ">="
107
107
  - !ruby/object:Gem::Version
108
- version: '1.2'
108
+ version: 1.2.3
109
109
  - - "<"
110
110
  - !ruby/object:Gem::Version
111
111
  version: '2'
@@ -115,7 +115,7 @@ dependencies:
115
115
  requirements:
116
116
  - - ">="
117
117
  - !ruby/object:Gem::Version
118
- version: '2.12'
118
+ version: 2.12.3
119
119
  - - "<"
120
120
  - !ruby/object:Gem::Version
121
121
  version: '3'
@@ -125,7 +125,7 @@ dependencies:
125
125
  requirements:
126
126
  - - ">="
127
127
  - !ruby/object:Gem::Version
128
- version: '2.12'
128
+ version: 2.12.3
129
129
  - - "<"
130
130
  - !ruby/object:Gem::Version
131
131
  version: '3'
@@ -135,7 +135,7 @@ dependencies:
135
135
  requirements:
136
136
  - - ">="
137
137
  - !ruby/object:Gem::Version
138
- version: '2.19'
138
+ version: 2.20.0
139
139
  - - "<"
140
140
  - !ruby/object:Gem::Version
141
141
  version: '3'
@@ -145,7 +145,7 @@ dependencies:
145
145
  requirements:
146
146
  - - ">="
147
147
  - !ruby/object:Gem::Version
148
- version: '2.19'
148
+ version: 2.20.0
149
149
  - - "<"
150
150
  - !ruby/object:Gem::Version
151
151
  version: '3'
@@ -155,7 +155,7 @@ dependencies:
155
155
  requirements:
156
156
  - - ">="
157
157
  - !ruby/object:Gem::Version
158
- version: '1.2'
158
+ version: 1.2.0
159
159
  - - "<"
160
160
  - !ruby/object:Gem::Version
161
161
  version: '2'
@@ -165,7 +165,7 @@ dependencies:
165
165
  requirements:
166
166
  - - ">="
167
167
  - !ruby/object:Gem::Version
168
- version: '1.2'
168
+ version: 1.2.0
169
169
  - - "<"
170
170
  - !ruby/object:Gem::Version
171
171
  version: '2'
@@ -175,7 +175,7 @@ dependencies:
175
175
  requirements:
176
176
  - - ">="
177
177
  - !ruby/object:Gem::Version
178
- version: '2.9'
178
+ version: 2.9.0
179
179
  - - "<"
180
180
  - !ruby/object:Gem::Version
181
181
  version: '3'
@@ -185,7 +185,7 @@ dependencies:
185
185
  requirements:
186
186
  - - ">="
187
187
  - !ruby/object:Gem::Version
188
- version: '2.9'
188
+ version: 2.9.0
189
189
  - - "<"
190
190
  - !ruby/object:Gem::Version
191
191
  version: '3'
@@ -195,7 +195,7 @@ dependencies:
195
195
  requirements:
196
196
  - - ">="
197
197
  - !ruby/object:Gem::Version
198
- version: '0.9'
198
+ version: 0.9.1
199
199
  - - "<"
200
200
  - !ruby/object:Gem::Version
201
201
  version: '1'
@@ -205,7 +205,7 @@ dependencies:
205
205
  requirements:
206
206
  - - ">="
207
207
  - !ruby/object:Gem::Version
208
- version: '0.9'
208
+ version: 0.9.1
209
209
  - - "<"
210
210
  - !ruby/object:Gem::Version
211
211
  version: '1'
@@ -215,7 +215,7 @@ dependencies:
215
215
  requirements:
216
216
  - - ">="
217
217
  - !ruby/object:Gem::Version
218
- version: '0.5'
218
+ version: 0.5.1
219
219
  - - "<"
220
220
  - !ruby/object:Gem::Version
221
221
  version: '1'
@@ -225,7 +225,7 @@ dependencies:
225
225
  requirements:
226
226
  - - ">="
227
227
  - !ruby/object:Gem::Version
228
- version: '0.5'
228
+ version: 0.5.1
229
229
  - - "<"
230
230
  - !ruby/object:Gem::Version
231
231
  version: '1'
@@ -235,7 +235,7 @@ dependencies:
235
235
  requirements:
236
236
  - - ">="
237
237
  - !ruby/object:Gem::Version
238
- version: '1.19'
238
+ version: 1.17.2
239
239
  - - "<"
240
240
  - !ruby/object:Gem::Version
241
241
  version: '2'
@@ -245,7 +245,7 @@ dependencies:
245
245
  requirements:
246
246
  - - ">="
247
247
  - !ruby/object:Gem::Version
248
- version: '1.19'
248
+ version: 1.17.2
249
249
  - - "<"
250
250
  - !ruby/object:Gem::Version
251
251
  version: '2'
@@ -255,7 +255,7 @@ dependencies:
255
255
  requirements:
256
256
  - - ">="
257
257
  - !ruby/object:Gem::Version
258
- version: '1.1'
258
+ version: 1.1.1
259
259
  - - "<"
260
260
  - !ruby/object:Gem::Version
261
261
  version: '2'
@@ -265,7 +265,7 @@ dependencies:
265
265
  requirements:
266
266
  - - ">="
267
267
  - !ruby/object:Gem::Version
268
- version: '1.1'
268
+ version: 1.1.1
269
269
  - - "<"
270
270
  - !ruby/object:Gem::Version
271
271
  version: '2'
@@ -275,7 +275,7 @@ dependencies:
275
275
  requirements:
276
276
  - - ">="
277
277
  - !ruby/object:Gem::Version
278
- version: '2.7'
278
+ version: 2.6.18
279
279
  - - "<"
280
280
  - !ruby/object:Gem::Version
281
281
  version: '3'
@@ -285,7 +285,7 @@ dependencies:
285
285
  requirements:
286
286
  - - ">="
287
287
  - !ruby/object:Gem::Version
288
- version: '2.7'
288
+ version: 2.6.18
289
289
  - - "<"
290
290
  - !ruby/object:Gem::Version
291
291
  version: '3'
@@ -318,6 +318,7 @@ files:
318
318
  - lib/code/extensions/nil_class.rb
319
319
  - lib/code/extensions/nokogiri.rb
320
320
  - lib/code/extensions/object.rb
321
+ - lib/code/extensions/regexp.rb
321
322
  - lib/code/extensions/string.rb
322
323
  - lib/code/extensions/symbol.rb
323
324
  - lib/code/extensions/true_class.rb
@@ -376,6 +377,7 @@ files:
376
377
  - lib/code/object/number.rb
377
378
  - lib/code/object/parameter.rb
378
379
  - lib/code/object/range.rb
380
+ - lib/code/object/regex.rb
379
381
  - lib/code/object/smtp.rb
380
382
  - lib/code/object/string.rb
381
383
  - lib/code/object/super.rb
@@ -401,14 +403,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
401
403
  requirements:
402
404
  - - ">="
403
405
  - !ruby/object:Gem::Version
404
- version: '3.0'
406
+ version: '4.0'
405
407
  required_rubygems_version: !ruby/object:Gem::Requirement
406
408
  requirements:
407
409
  - - ">="
408
410
  - !ruby/object:Gem::Version
409
411
  version: '0'
410
412
  requirements: []
411
- rubygems_version: 3.6.9
413
+ rubygems_version: 4.0.15
412
414
  specification_version: 4
413
415
  summary: a programming language for the internet
414
416
  test_files: []