code-ruby 3.1.2 → 4.0.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.
- checksums.yaml +4 -4
- data/VERSION +1 -1
- data/bin/code +97 -20
- data/lib/code/concerns/shared.rb +331 -15
- data/lib/code/format.rb +15 -1
- data/lib/code/network.rb +87 -0
- data/lib/code/node/call.rb +79 -2
- data/lib/code/node/call_argument.rb +14 -0
- data/lib/code/node/code.rb +5 -4
- data/lib/code/node/function_parameter.rb +7 -4
- data/lib/code/node/list.rb +29 -1
- data/lib/code/object/base_64.rb +132 -6
- data/lib/code/object/boolean.rb +60 -0
- data/lib/code/object/class.rb +138 -2
- data/lib/code/object/code.rb +111 -3
- data/lib/code/object/context.rb +57 -1
- data/lib/code/object/cryptography.rb +63 -0
- data/lib/code/object/date.rb +13339 -462
- data/lib/code/object/decimal.rb +1725 -0
- data/lib/code/object/dictionary.rb +1790 -11
- data/lib/code/object/duration.rb +28 -0
- data/lib/code/object/function.rb +261 -23
- data/lib/code/object/global.rb +534 -1
- data/lib/code/object/html.rb +179 -7
- data/lib/code/object/http.rb +244 -14
- data/lib/code/object/ics.rb +75 -13
- data/lib/code/object/identifier_list.rb +17 -2
- data/lib/code/object/integer.rb +1937 -2
- data/lib/code/object/json.rb +75 -1
- data/lib/code/object/list.rb +3383 -10
- data/lib/code/object/nothing.rb +53 -0
- data/lib/code/object/number.rb +110 -0
- data/lib/code/object/parameter.rb +140 -0
- data/lib/code/object/range.rb +576 -14
- data/lib/code/object/smtp.rb +95 -12
- data/lib/code/object/string.rb +944 -3
- data/lib/code/object/super.rb +10 -1
- data/lib/code/object/time.rb +13358 -498
- data/lib/code/object/url.rb +65 -0
- data/lib/code/object.rb +543 -0
- data/lib/code/parser.rb +161 -24
- data/lib/code-ruby.rb +3 -0
- data/lib/code.rb +30 -3
- metadata +135 -84
- data/.github/dependabot.yml +0 -15
- data/.github/workflows/ci.yml +0 -38
- data/.gitignore +0 -30
- data/.node-version +0 -1
- data/.npm-version +0 -1
- data/.prettierignore +0 -2
- data/.rspec +0 -1
- data/.rubocop.yml +0 -140
- data/.ruby-version +0 -1
- data/.tool-versions +0 -3
- data/AGENTS.md +0 -43
- data/Gemfile +0 -22
- data/Gemfile.lock +0 -292
- data/Rakefile +0 -5
- data/bin/bundle +0 -123
- data/bin/bundle-audit +0 -31
- data/bin/bundler-audit +0 -31
- data/bin/dorian +0 -31
- data/bin/rspec +0 -31
- data/bin/rubocop +0 -31
- data/bin/test +0 -5
- data/code-ruby.gemspec +0 -34
- data/docs/precedence.txt +0 -36
- data/package-lock.json +0 -14
- data/package.json +0 -7
- data/spec/bin/code_spec.rb +0 -48
- data/spec/code/format_spec.rb +0 -153
- data/spec/code/node/call_spec.rb +0 -11
- data/spec/code/object/boolean_spec.rb +0 -18
- data/spec/code/object/cryptography_spec.rb +0 -25
- data/spec/code/object/decimal_spec.rb +0 -50
- data/spec/code/object/dictionary_spec.rb +0 -98
- data/spec/code/object/function_spec.rb +0 -268
- data/spec/code/object/http_spec.rb +0 -33
- data/spec/code/object/ics_spec.rb +0 -50
- data/spec/code/object/integer_spec.rb +0 -42
- data/spec/code/object/list_spec.rb +0 -22
- data/spec/code/object/nothing_spec.rb +0 -14
- data/spec/code/object/range_spec.rb +0 -23
- data/spec/code/object/string_spec.rb +0 -26
- data/spec/code/parser/boolean_spec.rb +0 -11
- data/spec/code/parser/chained_call_spec.rb +0 -16
- data/spec/code/parser/dictionary_spec.rb +0 -18
- data/spec/code/parser/function_spec.rb +0 -16
- data/spec/code/parser/group_spec.rb +0 -11
- data/spec/code/parser/if_modifier_spec.rb +0 -18
- data/spec/code/parser/list_spec.rb +0 -17
- data/spec/code/parser/number_spec.rb +0 -11
- data/spec/code/parser/string_spec.rb +0 -20
- data/spec/code/parser_spec.rb +0 -52
- data/spec/code/type_spec.rb +0 -21
- data/spec/code_spec.rb +0 -717
- data/spec/spec_helper.rb +0 -21
- data/spec/zeitwerk/loader_spec.rb +0 -7
data/lib/code/object/url.rb
CHANGED
|
@@ -3,6 +3,57 @@
|
|
|
3
3
|
class Code
|
|
4
4
|
class Object
|
|
5
5
|
class Url < Object
|
|
6
|
+
CLASS_DOCUMENTATION = {
|
|
7
|
+
name: "Url",
|
|
8
|
+
description: "encodes text for urls, decodes url-escaped text, and parses strings as urls.",
|
|
9
|
+
examples: [
|
|
10
|
+
"Url.encode(\"hello world\")",
|
|
11
|
+
"Url.decode(\"a%2Fb%3Fx%3D1\")",
|
|
12
|
+
"Url.parse(\"https://example.com/a?b=1\")"
|
|
13
|
+
]
|
|
14
|
+
}.freeze
|
|
15
|
+
CLASS_FUNCTIONS = {
|
|
16
|
+
"encode" => {
|
|
17
|
+
name: "encode",
|
|
18
|
+
description: "returns url-escaped text for a value.",
|
|
19
|
+
examples: [
|
|
20
|
+
"Url.encode(\"hello world\")",
|
|
21
|
+
"Url.encode(\"a/b?x=1\")",
|
|
22
|
+
"Url.encode(:hello)"
|
|
23
|
+
]
|
|
24
|
+
},
|
|
25
|
+
"decode" => {
|
|
26
|
+
name: "decode",
|
|
27
|
+
description: "returns text decoded from url-escaped text.",
|
|
28
|
+
examples: [
|
|
29
|
+
"Url.decode(\"hello+world\")",
|
|
30
|
+
"Url.decode(\"a%2Fb%3Fx%3D1\")",
|
|
31
|
+
"Url.decode(Url.encode(\"a+b\"))"
|
|
32
|
+
]
|
|
33
|
+
},
|
|
34
|
+
"parse" => {
|
|
35
|
+
name: "parse",
|
|
36
|
+
description: "returns a url parsed from a value, or an empty url when parsing fails.",
|
|
37
|
+
examples: [
|
|
38
|
+
"Url.parse(\"https://example.com/a?b=1\")",
|
|
39
|
+
"Url.parse(\"/path\")",
|
|
40
|
+
"Url.parse(\"not a url\")"
|
|
41
|
+
]
|
|
42
|
+
}
|
|
43
|
+
}.freeze
|
|
44
|
+
|
|
45
|
+
def self.function_documentation(scope)
|
|
46
|
+
return CLASS_FUNCTIONS if scope == :class
|
|
47
|
+
|
|
48
|
+
{}
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def initialize(*args, **_kargs, &_block)
|
|
52
|
+
self.raw = ::URI.parse(args.first.to_s)
|
|
53
|
+
rescue ::URI::InvalidURIError
|
|
54
|
+
self.raw = ::URI.parse("")
|
|
55
|
+
end
|
|
56
|
+
|
|
6
57
|
def self.call(**args)
|
|
7
58
|
code_operator = args.fetch(:operator, nil).to_code
|
|
8
59
|
code_arguments = args.fetch(:arguments, []).to_code
|
|
@@ -11,6 +62,12 @@ class Code
|
|
|
11
62
|
when "encode"
|
|
12
63
|
sig(args) { Object.maybe }
|
|
13
64
|
code_encode(*code_arguments.raw)
|
|
65
|
+
when "decode"
|
|
66
|
+
sig(args) { Object.maybe }
|
|
67
|
+
code_decode(*code_arguments.raw)
|
|
68
|
+
when "parse"
|
|
69
|
+
sig(args) { Object.maybe }
|
|
70
|
+
code_parse(*code_arguments.raw)
|
|
14
71
|
else
|
|
15
72
|
super
|
|
16
73
|
end
|
|
@@ -21,6 +78,14 @@ class Code
|
|
|
21
78
|
|
|
22
79
|
String.new(CGI.escape(string.to_s))
|
|
23
80
|
end
|
|
81
|
+
|
|
82
|
+
def self.code_decode(string = nil)
|
|
83
|
+
String.new(CGI.unescape(string.to_s))
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def self.code_parse(string = nil)
|
|
87
|
+
new(string)
|
|
88
|
+
end
|
|
24
89
|
end
|
|
25
90
|
end
|
|
26
91
|
end
|
data/lib/code/object.rb
CHANGED
|
@@ -11,7 +11,501 @@ class Code
|
|
|
11
11
|
::String,
|
|
12
12
|
::BigDecimal
|
|
13
13
|
].freeze
|
|
14
|
+
CLASS_DOCUMENTATION = {
|
|
15
|
+
name: "Object",
|
|
16
|
+
description: "provides the shared behavior available to every value.",
|
|
17
|
+
examples: [
|
|
18
|
+
"Object",
|
|
19
|
+
"Object.new",
|
|
20
|
+
"Object.documentation.description"
|
|
21
|
+
]
|
|
22
|
+
}.freeze
|
|
23
|
+
INSTANCE_FUNCTIONS = {
|
|
24
|
+
"documentation" => {
|
|
25
|
+
name: "documentation",
|
|
26
|
+
description: "returns documentation for the value's class.",
|
|
27
|
+
examples: [
|
|
28
|
+
"1.documentation.name",
|
|
29
|
+
"[].documentation.description",
|
|
30
|
+
"{}.documentation.examples"
|
|
31
|
+
]
|
|
32
|
+
},
|
|
33
|
+
"functions" => {
|
|
34
|
+
name: "functions",
|
|
35
|
+
description: "returns documented instance and class functions available on the value.",
|
|
36
|
+
examples: [
|
|
37
|
+
"[].functions.keys.include?(:map)",
|
|
38
|
+
"1.functions.keys.include?(:to_string)",
|
|
39
|
+
"{}.functions.keys.include?(:fetch)"
|
|
40
|
+
]
|
|
41
|
+
},
|
|
42
|
+
"instance_functions" => {
|
|
43
|
+
name: "instance_functions",
|
|
44
|
+
description: "returns documented functions available on values of the receiver.",
|
|
45
|
+
examples: [
|
|
46
|
+
"[].instance_functions.keys.include?(:map)",
|
|
47
|
+
"1.instance_functions.keys.include?(:to_string)",
|
|
48
|
+
"{}.instance_functions.keys.include?(:fetch)"
|
|
49
|
+
]
|
|
50
|
+
},
|
|
51
|
+
"class_functions" => {
|
|
52
|
+
name: "class_functions",
|
|
53
|
+
description: "returns documented functions available on the receiver constructor.",
|
|
54
|
+
examples: [
|
|
55
|
+
"[].class_functions",
|
|
56
|
+
"List.class_functions.keys.include?(:new)",
|
|
57
|
+
"String.class_functions.keys.include?(:new)"
|
|
58
|
+
]
|
|
59
|
+
},
|
|
60
|
+
"respond_to?" => {
|
|
61
|
+
name: "respond_to?",
|
|
62
|
+
description: "returns whether the value responds to the named function.",
|
|
63
|
+
examples: [
|
|
64
|
+
"[].respond_to?(:map)",
|
|
65
|
+
"1.respond_to?(:zero?)",
|
|
66
|
+
"{}.respond_to?(:fetch)"
|
|
67
|
+
]
|
|
68
|
+
},
|
|
69
|
+
"present?" => {
|
|
70
|
+
name: "present?",
|
|
71
|
+
description: "returns whether the value is present.",
|
|
72
|
+
examples: ["1.present?", ":hello.present?", "[1].present?"]
|
|
73
|
+
},
|
|
74
|
+
"blank?" => {
|
|
75
|
+
name: "blank?",
|
|
76
|
+
description: "returns whether the value is blank.",
|
|
77
|
+
examples: ["nothing.blank?", "\"\".blank?", "[].blank?"]
|
|
78
|
+
},
|
|
79
|
+
"presence" => {
|
|
80
|
+
name: "presence",
|
|
81
|
+
description: "returns the value when present, otherwise nothing.",
|
|
82
|
+
examples: [":hello.presence", "\"\".presence", "[1].presence"]
|
|
83
|
+
},
|
|
84
|
+
"presence_in" => {
|
|
85
|
+
name: "presence_in",
|
|
86
|
+
description: "returns the value when it is included in the list, otherwise nothing.",
|
|
87
|
+
examples: [
|
|
88
|
+
"2.presence_in([1, 2, 3])",
|
|
89
|
+
"4.presence_in([1, 2, 3])",
|
|
90
|
+
"\"a\".presence_in([\"a\", \"b\"])"
|
|
91
|
+
]
|
|
92
|
+
},
|
|
93
|
+
"is_a?" => {
|
|
94
|
+
name: "is_a?",
|
|
95
|
+
description: "returns whether the value is an instance of the class or one of its subclasses.",
|
|
96
|
+
examples: ["1.is_a?(Integer)", ":a.is_a?(String)", "[].is_a?(List)"]
|
|
97
|
+
},
|
|
98
|
+
"is_an?" => {
|
|
99
|
+
name: "is_an?",
|
|
100
|
+
description: "alias for is_a?.",
|
|
101
|
+
examples: ["1.is_an?(Integer)", ":a.is_an?(String)", "[].is_an?(List)"]
|
|
102
|
+
},
|
|
103
|
+
"kind_of?" => {
|
|
104
|
+
name: "kind_of?",
|
|
105
|
+
description: "alias for is_a?.",
|
|
106
|
+
examples: ["1.kind_of?(Integer)", ":a.kind_of?(String)", "[].kind_of?(List)"]
|
|
107
|
+
},
|
|
108
|
+
"instance_of?" => {
|
|
109
|
+
name: "instance_of?",
|
|
110
|
+
description: "returns whether the value is exactly an instance of the class.",
|
|
111
|
+
examples: [
|
|
112
|
+
"1.instance_of?(Integer)",
|
|
113
|
+
":a.instance_of?(String)",
|
|
114
|
+
"[].instance_of?(List)"
|
|
115
|
+
]
|
|
116
|
+
},
|
|
117
|
+
"!" => {
|
|
118
|
+
name: "!",
|
|
119
|
+
description: "returns the boolean negation of the value.",
|
|
120
|
+
examples: ["!true", "!false", "!nothing"]
|
|
121
|
+
},
|
|
122
|
+
"not" => {
|
|
123
|
+
name: "not",
|
|
124
|
+
description: "returns the boolean negation of the value.",
|
|
125
|
+
examples: ["true.not", "false.not", "nothing.not"]
|
|
126
|
+
},
|
|
127
|
+
"!=" => {
|
|
128
|
+
name: "!=",
|
|
129
|
+
description: "returns whether the value is different from another value.",
|
|
130
|
+
examples: ["1 != 2", ":a != :b", "[1] != [2]"]
|
|
131
|
+
},
|
|
132
|
+
"different" => {
|
|
133
|
+
name: "different",
|
|
134
|
+
description: "returns whether the value is different from another value.",
|
|
135
|
+
examples: ["1.different(2)", ":a.different(:b)", "[1].different([2])"]
|
|
136
|
+
},
|
|
137
|
+
"&&" => {
|
|
138
|
+
name: "&&",
|
|
139
|
+
description: "returns the other value when the receiver is truthy, otherwise the receiver.",
|
|
140
|
+
examples: ["true && 1", "false && 1", "1 && 2"]
|
|
141
|
+
},
|
|
142
|
+
"and" => {
|
|
143
|
+
name: "and",
|
|
144
|
+
description: "returns the other value when the receiver is truthy, otherwise the receiver.",
|
|
145
|
+
examples: ["true.and(1)", "false.and(1)", "1.and(2)"]
|
|
146
|
+
},
|
|
147
|
+
"+" => {
|
|
148
|
+
name: "+",
|
|
149
|
+
description: "returns the receiver for object types that do not override plus.",
|
|
150
|
+
examples: ["+Object.new", "+nothing", "+[]"]
|
|
151
|
+
},
|
|
152
|
+
"self" => {
|
|
153
|
+
name: "self",
|
|
154
|
+
description: "returns the receiver.",
|
|
155
|
+
examples: ["1.self", ":a.self", "[].self"]
|
|
156
|
+
},
|
|
157
|
+
".." => {
|
|
158
|
+
name: "..",
|
|
159
|
+
description: "builds an inclusive range from the receiver to another value.",
|
|
160
|
+
examples: ["1..3", ":a..:c", "Date.today..Date.tomorrow"]
|
|
161
|
+
},
|
|
162
|
+
"inclusive_range" => {
|
|
163
|
+
name: "inclusive_range",
|
|
164
|
+
description: "builds an inclusive range from the receiver to another value.",
|
|
165
|
+
examples: [
|
|
166
|
+
"1.inclusive_range(3)",
|
|
167
|
+
":a.inclusive_range(:c)",
|
|
168
|
+
"Date.today.inclusive_range(Date.tomorrow)"
|
|
169
|
+
]
|
|
170
|
+
},
|
|
171
|
+
"..." => {
|
|
172
|
+
name: "...",
|
|
173
|
+
description: "builds an exclusive range from the receiver to another value.",
|
|
174
|
+
examples: ["1...3", ":a...:c", "Date.today...Date.tomorrow"]
|
|
175
|
+
},
|
|
176
|
+
"exclusive_range" => {
|
|
177
|
+
name: "exclusive_range",
|
|
178
|
+
description: "builds an exclusive range from the receiver to another value.",
|
|
179
|
+
examples: [
|
|
180
|
+
"1.exclusive_range(3)",
|
|
181
|
+
":a.exclusive_range(:c)",
|
|
182
|
+
"Date.today.exclusive_range(Date.tomorrow)"
|
|
183
|
+
]
|
|
184
|
+
},
|
|
185
|
+
"==" => {
|
|
186
|
+
name: "==",
|
|
187
|
+
description: "returns whether the value equals another value.",
|
|
188
|
+
examples: ["1 == 1", ":a == :a", "[1] == [1]"]
|
|
189
|
+
},
|
|
190
|
+
"equal" => {
|
|
191
|
+
name: "equal",
|
|
192
|
+
description: "returns whether the value equals another value.",
|
|
193
|
+
examples: ["1.equal(1)", ":a.equal(:a)", "[1].equal([1])"]
|
|
194
|
+
},
|
|
195
|
+
"equal?" => {
|
|
196
|
+
name: "equal?",
|
|
197
|
+
description: "returns whether the value equals another value.",
|
|
198
|
+
examples: ["1.equal?(1)", ":a.equal?(:a)", "[1].equal?([1])"]
|
|
199
|
+
},
|
|
200
|
+
"same_object?" => {
|
|
201
|
+
name: "same_object?",
|
|
202
|
+
description: "returns whether the value and argument are the same object.",
|
|
203
|
+
examples: [
|
|
204
|
+
"a = [] b = a a.same_object?(b)",
|
|
205
|
+
"[].same_object?([])",
|
|
206
|
+
"a = {} b = a a.same_object?(b)"
|
|
207
|
+
]
|
|
208
|
+
},
|
|
209
|
+
">" => {
|
|
210
|
+
name: ">",
|
|
211
|
+
description: "returns whether the value is greater than another value.",
|
|
212
|
+
examples: ["2 > 1", ":b > :a", "Date.tomorrow > Date.today"]
|
|
213
|
+
},
|
|
214
|
+
"greater" => {
|
|
215
|
+
name: "greater",
|
|
216
|
+
description: "returns whether the value is greater than another value.",
|
|
217
|
+
examples: [
|
|
218
|
+
"2.greater(1)",
|
|
219
|
+
":b.greater(:a)",
|
|
220
|
+
"Date.tomorrow.greater(Date.today)"
|
|
221
|
+
]
|
|
222
|
+
},
|
|
223
|
+
">=" => {
|
|
224
|
+
name: ">=",
|
|
225
|
+
description: "returns whether the value is greater than or equal to another value.",
|
|
226
|
+
examples: ["2 >= 2", ":b >= :a", "Date.today >= Date.today"]
|
|
227
|
+
},
|
|
228
|
+
"greater_or_equal" => {
|
|
229
|
+
name: "greater_or_equal",
|
|
230
|
+
description: "returns whether the value is greater than or equal to another value.",
|
|
231
|
+
examples: [
|
|
232
|
+
"2.greater_or_equal(2)",
|
|
233
|
+
":b.greater_or_equal(:a)",
|
|
234
|
+
"Date.today.greater_or_equal(Date.today)"
|
|
235
|
+
]
|
|
236
|
+
},
|
|
237
|
+
"<=>" => {
|
|
238
|
+
name: "<=>",
|
|
239
|
+
description: "compares the value with another value and returns -1, 0, or 1.",
|
|
240
|
+
examples: ["1 <=> 2", ":a <=> :b", "Date.today <=> Date.tomorrow"]
|
|
241
|
+
},
|
|
242
|
+
"compare" => {
|
|
243
|
+
name: "compare",
|
|
244
|
+
description: "compares the value with another value and returns -1, 0, or 1.",
|
|
245
|
+
examples: [
|
|
246
|
+
"1.compare(2)",
|
|
247
|
+
":a.compare(:b)",
|
|
248
|
+
"Date.today.compare(Date.tomorrow)"
|
|
249
|
+
]
|
|
250
|
+
},
|
|
251
|
+
"<" => {
|
|
252
|
+
name: "<",
|
|
253
|
+
description: "returns whether the value is less than another value.",
|
|
254
|
+
examples: ["1 < 2", ":a < :b", "Date.today < Date.tomorrow"]
|
|
255
|
+
},
|
|
256
|
+
"less" => {
|
|
257
|
+
name: "less",
|
|
258
|
+
description: "returns whether the value is less than another value.",
|
|
259
|
+
examples: ["1.less(2)", ":a.less(:b)", "Date.today.less(Date.tomorrow)"]
|
|
260
|
+
},
|
|
261
|
+
"<=" => {
|
|
262
|
+
name: "<=",
|
|
263
|
+
description: "returns whether the value is less than or equal to another value.",
|
|
264
|
+
examples: ["1 <= 1", ":a <= :b", "Date.today <= Date.today"]
|
|
265
|
+
},
|
|
266
|
+
"less_or_equal" => {
|
|
267
|
+
name: "less_or_equal",
|
|
268
|
+
description: "returns whether the value is less than or equal to another value.",
|
|
269
|
+
examples: [
|
|
270
|
+
"1.less_or_equal(1)",
|
|
271
|
+
":a.less_or_equal(:b)",
|
|
272
|
+
"Date.today.less_or_equal(Date.today)"
|
|
273
|
+
]
|
|
274
|
+
},
|
|
275
|
+
"===" => {
|
|
276
|
+
name: "===",
|
|
277
|
+
description: "returns whether the value strictly equals another value.",
|
|
278
|
+
examples: ["1 === 1", ":a === :a", "[1] === [1]"]
|
|
279
|
+
},
|
|
280
|
+
"strict_equal" => {
|
|
281
|
+
name: "strict_equal",
|
|
282
|
+
description: "returns whether the value strictly equals another value.",
|
|
283
|
+
examples: ["1.strict_equal(1)", ":a.strict_equal(:a)", "[1].strict_equal([1])"]
|
|
284
|
+
},
|
|
285
|
+
"!==" => {
|
|
286
|
+
name: "!==",
|
|
287
|
+
description: "returns whether the value does not strictly equal another value.",
|
|
288
|
+
examples: ["1 !== 2", ":a !== :b", "[1] !== [2]"]
|
|
289
|
+
},
|
|
290
|
+
"strict_different" => {
|
|
291
|
+
name: "strict_different",
|
|
292
|
+
description: "returns whether the value does not strictly equal another value.",
|
|
293
|
+
examples: [
|
|
294
|
+
"1.strict_different(2)",
|
|
295
|
+
":a.strict_different(:b)",
|
|
296
|
+
"[1].strict_different([2])"
|
|
297
|
+
]
|
|
298
|
+
},
|
|
299
|
+
"falsy?" => {
|
|
300
|
+
name: "falsy?",
|
|
301
|
+
description: "returns whether the value is falsy.",
|
|
302
|
+
examples: ["nothing.falsy?", "false.falsy?", "1.falsy?"]
|
|
303
|
+
},
|
|
304
|
+
"truthy?" => {
|
|
305
|
+
name: "truthy?",
|
|
306
|
+
description: "returns whether the value is truthy.",
|
|
307
|
+
examples: ["1.truthy?", "true.truthy?", "nothing.truthy?"]
|
|
308
|
+
},
|
|
309
|
+
"true?" => {
|
|
310
|
+
name: "true?",
|
|
311
|
+
description: "returns whether the value is true.",
|
|
312
|
+
examples: ["true.true?", "false.true?", "1.true?"]
|
|
313
|
+
},
|
|
314
|
+
"false?" => {
|
|
315
|
+
name: "false?",
|
|
316
|
+
description: "returns whether the value is false or nothing.",
|
|
317
|
+
examples: ["false.false?", "nothing.false?", "true.false?"]
|
|
318
|
+
},
|
|
319
|
+
"||" => {
|
|
320
|
+
name: "||",
|
|
321
|
+
description: "returns the receiver when truthy, otherwise the other value.",
|
|
322
|
+
examples: ["nothing || 1", "false || 1", "2 || 1"]
|
|
323
|
+
},
|
|
324
|
+
"or" => {
|
|
325
|
+
name: "or",
|
|
326
|
+
description: "returns the receiver when truthy, otherwise the other value.",
|
|
327
|
+
examples: ["nothing.or(1)", "false.or(1)", "2.or(1)"]
|
|
328
|
+
},
|
|
329
|
+
"to_boolean" => {
|
|
330
|
+
name: "to_boolean",
|
|
331
|
+
description: "converts the value to a boolean.",
|
|
332
|
+
examples: ["1.to_boolean", "nothing.to_boolean", "\"\".to_boolean"]
|
|
333
|
+
},
|
|
334
|
+
"to_class" => {
|
|
335
|
+
name: "to_class",
|
|
336
|
+
description: "converts the value to a class object.",
|
|
337
|
+
examples: ["1.to_class", ":a.to_class", "[].to_class"]
|
|
338
|
+
},
|
|
339
|
+
"to_date" => {
|
|
340
|
+
name: "to_date",
|
|
341
|
+
description: "converts the value to a date.",
|
|
342
|
+
examples: [
|
|
343
|
+
"\"2026-05-25\".to_date",
|
|
344
|
+
"Time.now.to_date",
|
|
345
|
+
"Date.today.to_date"
|
|
346
|
+
]
|
|
347
|
+
},
|
|
348
|
+
"to_decimal" => {
|
|
349
|
+
name: "to_decimal",
|
|
350
|
+
description: "converts the value to a decimal.",
|
|
351
|
+
examples: ["1.to_decimal", "\"1.5\".to_decimal", "2.0.to_decimal"]
|
|
352
|
+
},
|
|
353
|
+
"to_dictionary" => {
|
|
354
|
+
name: "to_dictionary",
|
|
355
|
+
description: "converts the value to a dictionary.",
|
|
356
|
+
examples: ["[].to_dictionary", "{}.to_dictionary", "[[:a, 1]].to_dictionary"]
|
|
357
|
+
},
|
|
358
|
+
"to_duration" => {
|
|
359
|
+
name: "to_duration",
|
|
360
|
+
description: "converts the value to a duration.",
|
|
361
|
+
examples: ["1.to_duration", "1.day.to_duration", "2.hours.to_duration"]
|
|
362
|
+
},
|
|
363
|
+
"to_integer" => {
|
|
364
|
+
name: "to_integer",
|
|
365
|
+
description: "converts the value to an integer.",
|
|
366
|
+
examples: ["\"1\".to_integer", "1.5.to_integer", "1.to_integer"]
|
|
367
|
+
},
|
|
368
|
+
"to_list" => {
|
|
369
|
+
name: "to_list",
|
|
370
|
+
description: "converts the value to a list.",
|
|
371
|
+
examples: ["1.to_list", "[1].to_list", "{}.to_list"]
|
|
372
|
+
},
|
|
373
|
+
"to_nothing" => {
|
|
374
|
+
name: "to_nothing",
|
|
375
|
+
description: "converts the value to nothing.",
|
|
376
|
+
examples: ["1.to_nothing", ":a.to_nothing", "[].to_nothing"]
|
|
377
|
+
},
|
|
378
|
+
"to_range" => {
|
|
379
|
+
name: "to_range",
|
|
380
|
+
description: "converts the value to a range.",
|
|
381
|
+
examples: ["1.to_range", "(1..3).to_range", "[1, 3].to_range"]
|
|
382
|
+
},
|
|
383
|
+
"to_string" => {
|
|
384
|
+
name: "to_string",
|
|
385
|
+
description: "converts the value to a string.",
|
|
386
|
+
examples: ["1.to_string", "true.to_string", ":a.to_string"]
|
|
387
|
+
},
|
|
388
|
+
"inspect" => {
|
|
389
|
+
name: "inspect",
|
|
390
|
+
description: "returns a string representation of the value for inspection.",
|
|
391
|
+
examples: ["1.inspect", ":a.inspect", "[1].inspect"]
|
|
392
|
+
},
|
|
393
|
+
"to_time" => {
|
|
394
|
+
name: "to_time",
|
|
395
|
+
description: "converts the value to a time.",
|
|
396
|
+
examples: [
|
|
397
|
+
"\"2026-05-25\".to_time",
|
|
398
|
+
"Date.today.to_time",
|
|
399
|
+
"Time.now.to_time"
|
|
400
|
+
]
|
|
401
|
+
},
|
|
402
|
+
"as_json" => {
|
|
403
|
+
name: "as_json",
|
|
404
|
+
description: "converts the value to a JSON-compatible value.",
|
|
405
|
+
examples: ["{ a: 1 }.as_json", "[1, 2].as_json", ":a.as_json"]
|
|
406
|
+
},
|
|
407
|
+
"duplicate" => {
|
|
408
|
+
name: "duplicate",
|
|
409
|
+
description: "returns a shallow duplicate of the value.",
|
|
410
|
+
examples: ["[1].duplicate", "{ a: 1 }.duplicate", ":a.duplicate"]
|
|
411
|
+
},
|
|
412
|
+
"deep_duplicate" => {
|
|
413
|
+
name: "deep_duplicate",
|
|
414
|
+
description: "returns a deep duplicate of the value.",
|
|
415
|
+
examples: [
|
|
416
|
+
"[{}].deep_duplicate",
|
|
417
|
+
"{ a: [1] }.deep_duplicate",
|
|
418
|
+
":a.deep_duplicate"
|
|
419
|
+
]
|
|
420
|
+
},
|
|
421
|
+
"to_parameter" => {
|
|
422
|
+
name: "to_parameter",
|
|
423
|
+
description: "converts the value to a URL parameter string.",
|
|
424
|
+
examples: [
|
|
425
|
+
"\"Hello world\".to_parameter",
|
|
426
|
+
"\"A/B\".to_parameter",
|
|
427
|
+
"123.to_parameter"
|
|
428
|
+
]
|
|
429
|
+
},
|
|
430
|
+
"to_json" => {
|
|
431
|
+
name: "to_json",
|
|
432
|
+
description: "serializes the value as JSON.",
|
|
433
|
+
examples: ["{ a: 1 }.to_json", "[1, 2].to_json", "\"a\".to_json"]
|
|
434
|
+
},
|
|
435
|
+
"send" => {
|
|
436
|
+
name: "send",
|
|
437
|
+
description: "calls a function by name with optional arguments.",
|
|
438
|
+
examples: [
|
|
439
|
+
"[1, 2].send(:size)",
|
|
440
|
+
":hello.send(:upcase)",
|
|
441
|
+
"1.send(:zero?)"
|
|
442
|
+
]
|
|
443
|
+
},
|
|
444
|
+
"itself" => {
|
|
445
|
+
name: "itself",
|
|
446
|
+
description: "returns the receiver.",
|
|
447
|
+
examples: ["1.itself", ":a.itself", "[].itself"]
|
|
448
|
+
},
|
|
449
|
+
"tap" => {
|
|
450
|
+
name: "tap",
|
|
451
|
+
description: "calls a function with the receiver and returns the receiver.",
|
|
452
|
+
examples: [
|
|
453
|
+
"1.tap((value) => { value })",
|
|
454
|
+
":a.tap((value) => { value.upcase })",
|
|
455
|
+
"[1].tap((value) => { value.size })"
|
|
456
|
+
]
|
|
457
|
+
},
|
|
458
|
+
"then" => {
|
|
459
|
+
name: "then",
|
|
460
|
+
description: "calls a function with the receiver and returns the function result.",
|
|
461
|
+
examples: [
|
|
462
|
+
"1.then((value) => { value + 1 })",
|
|
463
|
+
":a.then((value) => { value.upcase })",
|
|
464
|
+
"[1].then((value) => { value.size })"
|
|
465
|
+
]
|
|
466
|
+
},
|
|
467
|
+
"name" => {
|
|
468
|
+
name: "name",
|
|
469
|
+
description: "returns the value's class name.",
|
|
470
|
+
examples: ["1.name", ":a.name", "[].name"]
|
|
471
|
+
},
|
|
472
|
+
"nothing?" => {
|
|
473
|
+
name: "nothing?",
|
|
474
|
+
description: "returns whether the value is nothing.",
|
|
475
|
+
examples: ["nothing.nothing?", "1.nothing?", ":a.nothing?"]
|
|
476
|
+
},
|
|
477
|
+
"something?" => {
|
|
478
|
+
name: "something?",
|
|
479
|
+
description: "returns whether the value is not nothing.",
|
|
480
|
+
examples: ["1.something?", ":a.something?", "nothing.something?"]
|
|
481
|
+
}
|
|
482
|
+
}.freeze
|
|
483
|
+
CLASS_FUNCTIONS = {
|
|
484
|
+
"new" => {
|
|
485
|
+
name: "new",
|
|
486
|
+
description: "builds a new value for the class.",
|
|
487
|
+
examples: [
|
|
488
|
+
"List.new([1, 2])",
|
|
489
|
+
"String.new(:hello)",
|
|
490
|
+
"Dictionary.new(a: 1)"
|
|
491
|
+
]
|
|
492
|
+
}
|
|
493
|
+
}.freeze
|
|
14
494
|
|
|
495
|
+
def self.function_documentation(scope)
|
|
496
|
+
case scope
|
|
497
|
+
when :instance
|
|
498
|
+
INSTANCE_FUNCTIONS
|
|
499
|
+
when :class
|
|
500
|
+
CLASS_FUNCTIONS
|
|
501
|
+
else
|
|
502
|
+
{}
|
|
503
|
+
end
|
|
504
|
+
end
|
|
505
|
+
|
|
506
|
+
def self.class_documentation
|
|
507
|
+
self::CLASS_DOCUMENTATION
|
|
508
|
+
end
|
|
15
509
|
include Concerns::Shared
|
|
16
510
|
extend Concerns::Shared
|
|
17
511
|
|
|
@@ -34,6 +528,55 @@ class Code
|
|
|
34
528
|
new(*args)
|
|
35
529
|
end
|
|
36
530
|
|
|
531
|
+
def self.functions
|
|
532
|
+
class_functions
|
|
533
|
+
end
|
|
534
|
+
|
|
535
|
+
def self.documentation
|
|
536
|
+
documentation_for(self)
|
|
537
|
+
end
|
|
538
|
+
|
|
539
|
+
def self.instance_functions
|
|
540
|
+
documented_functions_for(self, :instance)
|
|
541
|
+
end
|
|
542
|
+
|
|
543
|
+
def self.class_functions
|
|
544
|
+
documented_functions_for(self, :class)
|
|
545
|
+
end
|
|
546
|
+
|
|
547
|
+
def self.documented_functions_for(klass, scope)
|
|
548
|
+
sorted_dictionary(function_documentation_for(klass, scope).transform_keys(&:to_s))
|
|
549
|
+
end
|
|
550
|
+
|
|
551
|
+
def self.documentation_for(klass)
|
|
552
|
+
Dictionary.new(klass.class_documentation.transform_keys(&:to_s))
|
|
553
|
+
end
|
|
554
|
+
|
|
555
|
+
def self.sorted_dictionary(raw)
|
|
556
|
+
Dictionary.new(raw.sort_by { |key, _value| key.to_s }.to_h)
|
|
557
|
+
end
|
|
558
|
+
|
|
559
|
+
def self.function_documentation_for(klass, scope)
|
|
560
|
+
documentation = function_documentation_registry_for(klass, scope)
|
|
561
|
+
inherited_function_documentation_for(klass, scope)
|
|
562
|
+
.merge(documentation)
|
|
563
|
+
end
|
|
564
|
+
|
|
565
|
+
def self.inherited_function_documentation_for(klass, scope)
|
|
566
|
+
return {} unless klass.is_a?(::Class)
|
|
567
|
+
|
|
568
|
+
superclass = klass.superclass
|
|
569
|
+
return {} unless superclass && superclass <= Object
|
|
570
|
+
|
|
571
|
+
function_documentation_for(superclass, scope)
|
|
572
|
+
rescue TypeError
|
|
573
|
+
{}
|
|
574
|
+
end
|
|
575
|
+
|
|
576
|
+
def self.function_documentation_registry_for(klass, scope)
|
|
577
|
+
klass.function_documentation(scope)
|
|
578
|
+
end
|
|
579
|
+
|
|
37
580
|
def name
|
|
38
581
|
self.class.name
|
|
39
582
|
end
|