code-ruby 4.0.0 → 4.0.2

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 (43) hide show
  1. checksums.yaml +4 -4
  2. data/VERSION +1 -1
  3. data/bin/code +21 -34
  4. data/lib/code/concerns/shared.rb +103 -99
  5. data/lib/code/format.rb +23 -19
  6. data/lib/code/network.rb +23 -28
  7. data/lib/code/node/call.rb +15 -9
  8. data/lib/code/node/code.rb +5 -5
  9. data/lib/code/node/function.rb +6 -1
  10. data/lib/code/node/left_operation.rb +3 -3
  11. data/lib/code/node/list.rb +10 -8
  12. data/lib/code/node/square_bracket.rb +2 -2
  13. data/lib/code/object/boolean.rb +13 -17
  14. data/lib/code/object/class.rb +33 -27
  15. data/lib/code/object/code.rb +4 -47
  16. data/lib/code/object/context.rb +8 -11
  17. data/lib/code/object/cryptography.rb +12 -6
  18. data/lib/code/object/date.rb +910 -449
  19. data/lib/code/object/decimal.rb +229 -856
  20. data/lib/code/object/dictionary.rb +116 -49
  21. data/lib/code/object/duration.rb +3 -7
  22. data/lib/code/object/function.rb +96 -54
  23. data/lib/code/object/global.rb +122 -209
  24. data/lib/code/object/html.rb +7 -13
  25. data/lib/code/object/http.rb +29 -43
  26. data/lib/code/object/ics.rb +6 -13
  27. data/lib/code/object/identifier_list.rb +16 -11
  28. data/lib/code/object/integer.rb +270 -942
  29. data/lib/code/object/json.rb +8 -28
  30. data/lib/code/object/list.rb +98 -114
  31. data/lib/code/object/nothing.rb +11 -11
  32. data/lib/code/object/number.rb +20 -10
  33. data/lib/code/object/parameter.rb +18 -9
  34. data/lib/code/object/range.rb +62 -108
  35. data/lib/code/object/smtp.rb +20 -15
  36. data/lib/code/object/string.rb +55 -29
  37. data/lib/code/object/super.rb +2 -1
  38. data/lib/code/object/time.rb +1146 -572
  39. data/lib/code/object/url.rb +4 -2
  40. data/lib/code/object.rb +119 -80
  41. data/lib/code/parser.rb +31 -92
  42. data/lib/code.rb +3 -11
  43. metadata +3 -23
@@ -5,7 +5,8 @@ class Code
5
5
  class Global < Object
6
6
  CLASS_DOCUMENTATION = {
7
7
  name: "Global",
8
- description: "dispatches top-level functions, constructors, and control flow helpers.",
8
+ description:
9
+ "dispatches top-level functions, constructors, and control flow helpers.",
9
10
  examples: [
10
11
  "globals.keys.include?(:puts)",
11
12
  "classes.keys.include?(:List)",
@@ -29,7 +30,8 @@ class Code
29
30
  },
30
31
  {
31
32
  name: "dictionary",
32
- description: "store named values in a dictionary and read them by key.",
33
+ description:
34
+ "store named values in a dictionary and read them by key.",
33
35
  source: "user = { name: :Dorian, age: 31 } user.name",
34
36
  expected: ":Dorian",
35
37
  command: "bin/code 'user = { name: :Dorian, age: 31 } user.name'"
@@ -76,7 +78,8 @@ class Code
76
78
  },
77
79
  {
78
80
  title: "Find built-in functions",
79
- action: "use globals, functions, instance_functions, and class_functions from inside Code.",
81
+ action:
82
+ "use globals, functions, instance_functions, and class_functions from inside Code.",
80
83
  example: GETTING_STARTED_EXAMPLES.fetch(4)
81
84
  }
82
85
  ],
@@ -90,254 +93,178 @@ class Code
90
93
  FUNCTIONS = {
91
94
  "Base64" => {
92
95
  name: "Base64",
93
- description: "returns the Base64 class when called without arguments, otherwise calls Base64.new.",
94
- examples: [
95
- "Base64",
96
- "Base64.new",
97
- "Base64.new(nothing)"
98
- ]
96
+ description:
97
+ "returns the Base64 class when called without arguments, otherwise calls Base64.new.",
98
+ examples: %w[Base64 Base64.new Base64.new(nothing)]
99
99
  },
100
100
  "Boolean" => {
101
101
  name: "Boolean",
102
- description: "returns the Boolean class when called without arguments, otherwise calls Boolean.new.",
103
- examples: [
104
- "Boolean",
105
- "Boolean.new",
106
- "Boolean.new(nothing)"
107
- ]
102
+ description:
103
+ "returns the Boolean class when called without arguments, otherwise calls Boolean.new.",
104
+ examples: %w[Boolean Boolean.new Boolean.new(nothing)]
108
105
  },
109
106
  "Class" => {
110
107
  name: "Class",
111
- description: "returns the Class class when called without arguments, otherwise calls Class.new.",
112
- examples: [
113
- "Class",
114
- "Class.new",
115
- "Class.new(nothing)"
116
- ]
108
+ description:
109
+ "returns the Class class when called without arguments, otherwise calls Class.new.",
110
+ examples: %w[Class Class.new Class.new(nothing)]
117
111
  },
118
112
  "Code" => {
119
113
  name: "Code",
120
- description: "returns the Code class when called without arguments, otherwise calls Code.new.",
121
- examples: [
122
- "Code",
123
- "Code.new",
124
- "Code.new(nothing)"
125
- ]
114
+ description:
115
+ "returns the Code class when called without arguments, otherwise calls Code.new.",
116
+ examples: %w[Code Code.new Code.new(nothing)]
126
117
  },
127
118
  "Context" => {
128
119
  name: "Context",
129
- description: "returns the Context class when called without arguments, otherwise calls Context.new.",
130
- examples: [
131
- "Context",
132
- "Context.new",
133
- "Context.new(nothing)"
134
- ]
120
+ description:
121
+ "returns the Context class when called without arguments, otherwise calls Context.new.",
122
+ examples: %w[Context Context.new Context.new(nothing)]
135
123
  },
136
124
  "Cryptography" => {
137
125
  name: "Cryptography",
138
- description: "returns the Cryptography class when called without arguments, otherwise calls Cryptography.new.",
139
- examples: [
140
- "Cryptography",
141
- "Cryptography.new",
142
- "Cryptography.new(nothing)"
143
- ]
126
+ description:
127
+ "returns the Cryptography class when called without arguments, otherwise calls Cryptography.new.",
128
+ examples: %w[Cryptography Cryptography.new Cryptography.new(nothing)]
144
129
  },
145
130
  "Date" => {
146
131
  name: "Date",
147
- description: "returns the Date class when called without arguments, otherwise calls Date.new.",
148
- examples: [
149
- "Date",
150
- "Date.new",
151
- "Date.new(nothing)"
152
- ]
132
+ description:
133
+ "returns the Date class when called without arguments, otherwise calls Date.new.",
134
+ examples: %w[Date Date.new Date.new(nothing)]
153
135
  },
154
136
  "Decimal" => {
155
137
  name: "Decimal",
156
- description: "returns the Decimal class when called without arguments, otherwise calls Decimal.new.",
157
- examples: [
158
- "Decimal",
159
- "Decimal.new",
160
- "Decimal.new(nothing)"
161
- ]
138
+ description:
139
+ "returns the Decimal class when called without arguments, otherwise calls Decimal.new.",
140
+ examples: %w[Decimal Decimal.new Decimal.new(nothing)]
162
141
  },
163
142
  "Dictionary" => {
164
143
  name: "Dictionary",
165
- description: "returns the Dictionary class when called without arguments, otherwise calls Dictionary.new.",
166
- examples: [
167
- "Dictionary",
168
- "Dictionary.new",
169
- "Dictionary.new(nothing)"
170
- ]
144
+ description:
145
+ "returns the Dictionary class when called without arguments, otherwise calls Dictionary.new.",
146
+ examples: %w[Dictionary Dictionary.new Dictionary.new(nothing)]
171
147
  },
172
148
  "Duration" => {
173
149
  name: "Duration",
174
- description: "returns the Duration class when called without arguments, otherwise calls Duration.new.",
175
- examples: [
176
- "Duration",
177
- "Duration.new",
178
- "Duration.new(nothing)"
179
- ]
150
+ description:
151
+ "returns the Duration class when called without arguments, otherwise calls Duration.new.",
152
+ examples: %w[Duration Duration.new Duration.new(nothing)]
180
153
  },
181
154
  "Function" => {
182
155
  name: "Function",
183
- description: "returns the Function class when called without arguments, otherwise calls Function.new.",
184
- examples: [
185
- "Function",
186
- "Function.new",
187
- "Function.new(nothing)"
188
- ]
156
+ description:
157
+ "returns the Function class when called without arguments, otherwise calls Function.new.",
158
+ examples: %w[Function Function.new Function.new(nothing)]
189
159
  },
190
160
  "Html" => {
191
161
  name: "Html",
192
- description: "returns the Html class when called without arguments, otherwise calls Html.new.",
193
- examples: [
194
- "Html",
195
- "Html.new",
196
- "Html.new(nothing)"
197
- ]
162
+ description:
163
+ "returns the Html class when called without arguments, otherwise calls Html.new.",
164
+ examples: %w[Html Html.new Html.new(nothing)]
198
165
  },
199
166
  "Http" => {
200
167
  name: "Http",
201
- description: "returns the Http class when called without arguments, otherwise calls Http.new.",
202
- examples: [
203
- "Http",
204
- "Http.new",
205
- "Http.new(nothing)"
206
- ]
168
+ description:
169
+ "returns the Http class when called without arguments, otherwise calls Http.new.",
170
+ examples: %w[Http Http.new Http.new(nothing)]
207
171
  },
208
172
  "Ics" => {
209
173
  name: "Ics",
210
- description: "returns the Ics class when called without arguments, otherwise calls Ics.new.",
211
- examples: [
212
- "Ics",
213
- "Ics.new",
214
- "Ics.new(nothing)"
215
- ]
174
+ description:
175
+ "returns the Ics class when called without arguments, otherwise calls Ics.new.",
176
+ examples: %w[Ics Ics.new Ics.new(nothing)]
216
177
  },
217
178
  "IdentifierList" => {
218
179
  name: "IdentifierList",
219
- description: "returns the IdentifierList class when called without arguments, otherwise calls IdentifierList.new.",
220
- examples: [
221
- "IdentifierList",
222
- "IdentifierList.new",
223
- "IdentifierList.new(nothing)"
180
+ description:
181
+ "returns the IdentifierList class when called without arguments, otherwise calls IdentifierList.new.",
182
+ examples: %w[
183
+ IdentifierList
184
+ IdentifierList.new
185
+ IdentifierList.new(nothing)
224
186
  ]
225
187
  },
226
188
  "Integer" => {
227
189
  name: "Integer",
228
- description: "returns the Integer class when called without arguments, otherwise calls Integer.new.",
229
- examples: [
230
- "Integer",
231
- "Integer.new",
232
- "Integer.new(nothing)"
233
- ]
190
+ description:
191
+ "returns the Integer class when called without arguments, otherwise calls Integer.new.",
192
+ examples: %w[Integer Integer.new Integer.new(nothing)]
234
193
  },
235
194
  "Json" => {
236
195
  name: "Json",
237
- description: "returns the Json class when called without arguments, otherwise calls Json.new.",
238
- examples: [
239
- "Json",
240
- "Json.new",
241
- "Json.new(nothing)"
242
- ]
196
+ description:
197
+ "returns the Json class when called without arguments, otherwise calls Json.new.",
198
+ examples: %w[Json Json.new Json.new(nothing)]
243
199
  },
244
200
  "List" => {
245
201
  name: "List",
246
- description: "returns the List class when called without arguments, otherwise calls List.new.",
247
- examples: [
248
- "List",
249
- "List.new",
250
- "List.new(nothing)"
251
- ]
202
+ description:
203
+ "returns the List class when called without arguments, otherwise calls List.new.",
204
+ examples: %w[List List.new List.new(nothing)]
252
205
  },
253
206
  "Nothing" => {
254
207
  name: "Nothing",
255
- description: "returns the Nothing class when called without arguments, otherwise calls Nothing.new.",
256
- examples: [
257
- "Nothing",
258
- "Nothing.new",
259
- "Nothing.new(nothing)"
260
- ]
208
+ description:
209
+ "returns the Nothing class when called without arguments, otherwise calls Nothing.new.",
210
+ examples: %w[Nothing Nothing.new Nothing.new(nothing)]
261
211
  },
262
212
  "Number" => {
263
213
  name: "Number",
264
- description: "returns the Number class when called without arguments, otherwise calls Number.new.",
265
- examples: [
266
- "Number",
267
- "Number.new",
268
- "Number.new(nothing)"
269
- ]
214
+ description:
215
+ "returns the Number class when called without arguments, otherwise calls Number.new.",
216
+ examples: %w[Number Number.new Number.new(nothing)]
270
217
  },
271
218
  "Object" => {
272
219
  name: "Object",
273
- description: "returns the Object class when called without arguments, otherwise calls Object.new.",
274
- examples: [
275
- "Object",
276
- "Object.new",
277
- "Object.new(nothing)"
278
- ]
220
+ description:
221
+ "returns the Object class when called without arguments, otherwise calls Object.new.",
222
+ examples: %w[Object Object.new Object.new(nothing)]
279
223
  },
280
224
  "Parameter" => {
281
225
  name: "Parameter",
282
- description: "returns the Parameter class when called without arguments, otherwise calls Parameter.new.",
283
- examples: [
284
- "Parameter",
285
- "Parameter.new",
286
- "Parameter.new(nothing)"
287
- ]
226
+ description:
227
+ "returns the Parameter class when called without arguments, otherwise calls Parameter.new.",
228
+ examples: %w[Parameter Parameter.new Parameter.new(nothing)]
288
229
  },
289
230
  "Range" => {
290
231
  name: "Range",
291
- description: "returns the Range class when called without arguments, otherwise calls Range.new.",
292
- examples: [
293
- "Range",
294
- "Range.new",
295
- "Range.new(nothing)"
296
- ]
232
+ description:
233
+ "returns the Range class when called without arguments, otherwise calls Range.new.",
234
+ examples: %w[Range Range.new Range.new(nothing)]
297
235
  },
298
236
  "Smtp" => {
299
237
  name: "Smtp",
300
- description: "returns the Smtp class when called without arguments, otherwise calls Smtp.new.",
301
- examples: [
302
- "Smtp",
303
- "Smtp.new",
304
- "Smtp.new(nothing)"
305
- ]
238
+ description:
239
+ "returns the Smtp class when called without arguments, otherwise calls Smtp.new.",
240
+ examples: %w[Smtp Smtp.new Smtp.new(nothing)]
306
241
  },
307
242
  "String" => {
308
243
  name: "String",
309
- description: "returns the String class when called without arguments, otherwise calls String.new.",
310
- examples: [
311
- "String",
312
- "String.new",
313
- "String.new(nothing)"
314
- ]
244
+ description:
245
+ "returns the String class when called without arguments, otherwise calls String.new.",
246
+ examples: %w[String String.new String.new(nothing)]
315
247
  },
316
248
  "Time" => {
317
249
  name: "Time",
318
- description: "returns the Time class when called without arguments, otherwise calls Time.new.",
319
- examples: [
320
- "Time",
321
- "Time.new",
322
- "Time.new(nothing)"
323
- ]
250
+ description:
251
+ "returns the Time class when called without arguments, otherwise calls Time.new.",
252
+ examples: %w[Time Time.new Time.new(nothing)]
324
253
  },
325
254
  "Url" => {
326
255
  name: "Url",
327
- description: "returns the Url class when called without arguments, otherwise calls Url.new.",
328
- examples: [
329
- "Url",
330
- "Url.new",
331
- "Url.new(nothing)"
332
- ]
256
+ description:
257
+ "returns the Url class when called without arguments, otherwise calls Url.new.",
258
+ examples: %w[Url Url.new Url.new(nothing)]
333
259
  },
334
260
  "classes" => {
335
261
  name: "classes",
336
- description: "returns documentation for built-in classes exposed by globals.",
337
- examples: [
338
- "classes",
339
- "classes.keys.include?(:List)",
340
- "classes.fetch(:String).description"
262
+ description:
263
+ "returns documentation for built-in classes exposed by globals.",
264
+ examples: %w[
265
+ classes
266
+ classes.keys.include?(:List)
267
+ classes.fetch(:String).description
341
268
  ]
342
269
  },
343
270
  "break" => {
@@ -361,15 +288,12 @@ class Code
361
288
  "context" => {
362
289
  name: "context",
363
290
  description: "returns the current evaluation context dictionary.",
364
- examples: [
365
- "context",
366
- "context.keys",
367
- "context.has_key?(:context)"
368
- ]
291
+ examples: %w[context context.keys context.has_key?(:context)]
369
292
  },
370
293
  "evaluate" => {
371
294
  name: "evaluate",
372
- description: "evaluates a string as Code source and returns its result.",
295
+ description:
296
+ "evaluates a string as Code source and returns its result.",
373
297
  examples: [
374
298
  "evaluate(\"1 + 2\")",
375
299
  "evaluate(\":hello\")",
@@ -378,25 +302,28 @@ class Code
378
302
  },
379
303
  "getting_started" => {
380
304
  name: "getting_started",
381
- description: "returns a short guide with runnable examples and commands.",
382
- examples: [
383
- "getting_started.title",
384
- "getting_started.steps.first.command",
385
- "getting_started.examples.map(&:name)"
305
+ description:
306
+ "returns a short guide with runnable examples and commands.",
307
+ examples: %w[
308
+ getting_started.title
309
+ getting_started.steps.first.command
310
+ getting_started.examples.map(&:name)
386
311
  ]
387
312
  },
388
313
  "globals" => {
389
314
  name: "globals",
390
- description: "returns documentation for top-level functions and constructors.",
391
- examples: [
392
- "globals",
393
- "globals.keys.include?(:List)",
394
- "globals.fetch(:puts).description"
315
+ description:
316
+ "returns documentation for top-level functions and constructors.",
317
+ examples: %w[
318
+ globals
319
+ globals.keys.include?(:List)
320
+ globals.fetch(:puts).description
395
321
  ]
396
322
  },
397
323
  "next" => {
398
324
  name: "next",
399
- description: "exits the current block iteration and returns an optional value.",
325
+ description:
326
+ "exits the current block iteration and returns an optional value.",
400
327
  examples: [
401
328
  "[1].map { next }",
402
329
  "[1].map { next 2 }",
@@ -406,38 +333,23 @@ class Code
406
333
  "p" => {
407
334
  name: "p",
408
335
  description: "writes inspected values to output and returns nothing.",
409
- examples: [
410
- "p(:hello)",
411
- "p(1, 2)",
412
- "p([1, 2])"
413
- ]
336
+ examples: ["p(:hello)", "p(1, 2)", "p([1, 2])"]
414
337
  },
415
338
  "print" => {
416
339
  name: "print",
417
340
  description: "writes values to output without adding a newline.",
418
- examples: [
419
- "print(:hello)",
420
- "print(1, 2)",
421
- "print(\"hello\")"
422
- ]
341
+ examples: ["print(:hello)", "print(1, 2)", "print(\"hello\")"]
423
342
  },
424
343
  "puts" => {
425
344
  name: "puts",
426
- description: "writes values to output with newlines and returns nothing.",
427
- examples: [
428
- "puts(:hello)",
429
- "puts(1, 2)",
430
- "puts(\"hello\")"
431
- ]
345
+ description:
346
+ "writes values to output with newlines and returns nothing.",
347
+ examples: ["puts(:hello)", "puts(1, 2)", "puts(\"hello\")"]
432
348
  },
433
349
  "read" => {
434
350
  name: "read",
435
351
  description: "reads one line from input.",
436
- examples: [
437
- "read",
438
- "name = read",
439
- "read.to_string"
440
- ]
352
+ examples: ["read", "name = read", "read.to_string"]
441
353
  },
442
354
  "redo" => {
443
355
  name: "redo",
@@ -459,7 +371,8 @@ class Code
459
371
  },
460
372
  "return" => {
461
373
  name: "return",
462
- description: "exits the current function and returns an optional value.",
374
+ description:
375
+ "exits the current function and returns an optional value.",
463
376
  examples: [
464
377
  "() => { return }",
465
378
  "() => { return 1 }",
@@ -622,7 +535,7 @@ class Code
622
535
  end
623
536
  when "context"
624
537
  sig(args)
625
- code_context.code_deep_duplicate
538
+ code_context
626
539
  when "Object"
627
540
  sig(args)
628
541
  if code_arguments.any?
@@ -51,7 +51,8 @@ class Code
51
51
  },
52
52
  "raw" => {
53
53
  name: "raw",
54
- description: "parses markup into an html fragment without escaping text.",
54
+ description:
55
+ "parses markup into an html fragment without escaping text.",
55
56
  examples: [
56
57
  "Html.raw(\"<strong>hello</strong>\")",
57
58
  "Html.raw(Html.text(:hello))",
@@ -80,7 +81,8 @@ class Code
80
81
  },
81
82
  "map" => {
82
83
  name: "map",
83
- description: "returns a list by calling a function for each html node.",
84
+ description:
85
+ "returns a list by calling a function for each html node.",
84
86
  examples: [
85
87
  "Html.raw(\"<p>a</p><p>b</p>\").css(\"p\").map((node) => { node.to_string })",
86
88
  "Html.raw(\"<p>a</p>\").css(:p).map((node, index) => { index })",
@@ -263,7 +265,6 @@ class Code
263
265
  args.first
264
266
  else
265
267
  source = args.first.to_s
266
- ::Code.ensure_input_size!(source, label: "html")
267
268
  Nokogiri.HTML(source)
268
269
  end
269
270
  end
@@ -383,10 +384,7 @@ class Code
383
384
  value_or_function.to_code
384
385
  end
385
386
 
386
- source = code_value.to_s
387
- ::Code.ensure_input_size!(source, label: "html")
388
-
389
- String.new(Nokogiri::HTML.fragment(source).text)
387
+ String.new(Nokogiri::HTML.fragment(code_value.to_s).text)
390
388
  rescue Error::Break => e
391
389
  e.code_value
392
390
  end
@@ -471,18 +469,14 @@ class Code
471
469
  if code_value.is_an?(Html)
472
470
  Html.new(fragment_from_html(code_value))
473
471
  else
474
- source = code_value.to_s
475
- ::Code.ensure_input_size!(source, label: "html")
476
- Html.new(Nokogiri::HTML::DocumentFragment.parse(source))
472
+ Html.new(Nokogiri::HTML::DocumentFragment.parse(code_value.to_s))
477
473
  end
478
474
  rescue Error::Break => e
479
475
  e.code_value
480
476
  end
481
477
 
482
478
  def self.fragment_from_html(html)
483
- source = html.to_html
484
- ::Code.ensure_input_size!(source, label: "html")
485
- Nokogiri::HTML::DocumentFragment.parse(source)
479
+ Nokogiri::HTML::DocumentFragment.parse(html.to_html)
486
480
  end
487
481
 
488
482
  def call(**args)