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.
Files changed (98) hide show
  1. checksums.yaml +4 -4
  2. data/VERSION +1 -1
  3. data/bin/code +97 -20
  4. data/lib/code/concerns/shared.rb +331 -15
  5. data/lib/code/format.rb +15 -1
  6. data/lib/code/network.rb +87 -0
  7. data/lib/code/node/call.rb +79 -2
  8. data/lib/code/node/call_argument.rb +14 -0
  9. data/lib/code/node/code.rb +5 -4
  10. data/lib/code/node/function_parameter.rb +7 -4
  11. data/lib/code/node/list.rb +29 -1
  12. data/lib/code/object/base_64.rb +132 -6
  13. data/lib/code/object/boolean.rb +60 -0
  14. data/lib/code/object/class.rb +138 -2
  15. data/lib/code/object/code.rb +111 -3
  16. data/lib/code/object/context.rb +57 -1
  17. data/lib/code/object/cryptography.rb +63 -0
  18. data/lib/code/object/date.rb +13339 -462
  19. data/lib/code/object/decimal.rb +1725 -0
  20. data/lib/code/object/dictionary.rb +1790 -11
  21. data/lib/code/object/duration.rb +28 -0
  22. data/lib/code/object/function.rb +261 -23
  23. data/lib/code/object/global.rb +534 -1
  24. data/lib/code/object/html.rb +179 -7
  25. data/lib/code/object/http.rb +244 -14
  26. data/lib/code/object/ics.rb +75 -13
  27. data/lib/code/object/identifier_list.rb +17 -2
  28. data/lib/code/object/integer.rb +1937 -2
  29. data/lib/code/object/json.rb +75 -1
  30. data/lib/code/object/list.rb +3383 -10
  31. data/lib/code/object/nothing.rb +53 -0
  32. data/lib/code/object/number.rb +110 -0
  33. data/lib/code/object/parameter.rb +140 -0
  34. data/lib/code/object/range.rb +576 -14
  35. data/lib/code/object/smtp.rb +95 -12
  36. data/lib/code/object/string.rb +944 -3
  37. data/lib/code/object/super.rb +10 -1
  38. data/lib/code/object/time.rb +13358 -498
  39. data/lib/code/object/url.rb +65 -0
  40. data/lib/code/object.rb +543 -0
  41. data/lib/code/parser.rb +161 -24
  42. data/lib/code-ruby.rb +3 -0
  43. data/lib/code.rb +30 -3
  44. metadata +135 -84
  45. data/.github/dependabot.yml +0 -15
  46. data/.github/workflows/ci.yml +0 -38
  47. data/.gitignore +0 -30
  48. data/.node-version +0 -1
  49. data/.npm-version +0 -1
  50. data/.prettierignore +0 -2
  51. data/.rspec +0 -1
  52. data/.rubocop.yml +0 -140
  53. data/.ruby-version +0 -1
  54. data/.tool-versions +0 -3
  55. data/AGENTS.md +0 -43
  56. data/Gemfile +0 -22
  57. data/Gemfile.lock +0 -292
  58. data/Rakefile +0 -5
  59. data/bin/bundle +0 -123
  60. data/bin/bundle-audit +0 -31
  61. data/bin/bundler-audit +0 -31
  62. data/bin/dorian +0 -31
  63. data/bin/rspec +0 -31
  64. data/bin/rubocop +0 -31
  65. data/bin/test +0 -5
  66. data/code-ruby.gemspec +0 -34
  67. data/docs/precedence.txt +0 -36
  68. data/package-lock.json +0 -14
  69. data/package.json +0 -7
  70. data/spec/bin/code_spec.rb +0 -48
  71. data/spec/code/format_spec.rb +0 -153
  72. data/spec/code/node/call_spec.rb +0 -11
  73. data/spec/code/object/boolean_spec.rb +0 -18
  74. data/spec/code/object/cryptography_spec.rb +0 -25
  75. data/spec/code/object/decimal_spec.rb +0 -50
  76. data/spec/code/object/dictionary_spec.rb +0 -98
  77. data/spec/code/object/function_spec.rb +0 -268
  78. data/spec/code/object/http_spec.rb +0 -33
  79. data/spec/code/object/ics_spec.rb +0 -50
  80. data/spec/code/object/integer_spec.rb +0 -42
  81. data/spec/code/object/list_spec.rb +0 -22
  82. data/spec/code/object/nothing_spec.rb +0 -14
  83. data/spec/code/object/range_spec.rb +0 -23
  84. data/spec/code/object/string_spec.rb +0 -26
  85. data/spec/code/parser/boolean_spec.rb +0 -11
  86. data/spec/code/parser/chained_call_spec.rb +0 -16
  87. data/spec/code/parser/dictionary_spec.rb +0 -18
  88. data/spec/code/parser/function_spec.rb +0 -16
  89. data/spec/code/parser/group_spec.rb +0 -11
  90. data/spec/code/parser/if_modifier_spec.rb +0 -18
  91. data/spec/code/parser/list_spec.rb +0 -17
  92. data/spec/code/parser/number_spec.rb +0 -11
  93. data/spec/code/parser/string_spec.rb +0 -20
  94. data/spec/code/parser_spec.rb +0 -52
  95. data/spec/code/type_spec.rb +0 -21
  96. data/spec/code_spec.rb +0 -717
  97. data/spec/spec_helper.rb +0 -21
  98. data/spec/zeitwerk/loader_spec.rb +0 -7
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2495002bb8e1d284386f2a90ff600370cfe0490a356688426682ec106727fbb3
4
- data.tar.gz: e8dffdf7d8d0c0e62a091d2a7d305eae48dc74d024aa26c5a8dc393763147f13
3
+ metadata.gz: 79da8875ffac10dd65ca8098ec782caac2822a70f261e2902dd652dfd87da312
4
+ data.tar.gz: 8120dd6eeaf76dd5b1d1e5ffe9114050ddf99a037b3506487e94814b7a39b794
5
5
  SHA512:
6
- metadata.gz: 55ceb13028c588110d3adec5539995ddd1f2dc4fd7173fd067a8e009a8093610adb150de78be46dfc57e605dbad0f03dd89e5693820be31c6d61c3440fb129ea
7
- data.tar.gz: 6ae82061c1a129f1607eb348e18917e75c7d23accf7dca589da00ed3ae34eccf76af79826e430f5267b4a2011ce7c9df8a1709069f95f660c8dff22d16c0c37a
6
+ metadata.gz: c7a12d5824757713528707a89ba8680e005502e83d22fd946d6a9bb45b67dca6b73d6ce684c737e8225c1feb761ac40b7feb3b8d308fc6c008e20b425ab945b3
7
+ data.tar.gz: d3d3e80c38fc4eec30b929947e59d12a463ad40ceb03fd1122fbbfdc7056f33d054eb240d94472264957ea2a8a71ef8e8685a11a5da4e73f29480959239daf11
data/VERSION CHANGED
@@ -1 +1 @@
1
- 3.1.2
1
+ 4.0.0
data/bin/code CHANGED
@@ -37,51 +37,128 @@ parsed =
37
37
  abort Code::Version.to_s if parsed.options.version
38
38
  abort parsed.help if parsed.options.help
39
39
 
40
+ MAX_ARGUMENT_FILES = 1000
41
+
40
42
  def glob_pattern?(value)
41
43
  value.match?(/[*?\[\]{]/)
42
44
  end
43
45
 
44
- expanded_argument_files = []
45
- remaining_arguments = []
46
+ def timeout
47
+ @timeout ||= @parsed_timeout
48
+ end
49
+
50
+ def with_timeout(&)
51
+ Timeout.timeout(timeout, &)
52
+ rescue Timeout::Error
53
+ raise Code::Error, "timeout"
54
+ end
55
+
56
+ def append_limited(buffer, value, label: "input")
57
+ value = value.to_s
58
+ if buffer.bytesize + value.bytesize > Code::MAX_INPUT_BYTES
59
+ raise Code::Error, "#{label} is too large"
60
+ end
61
+
62
+ buffer << value
63
+ end
64
+
65
+ def read_file(path)
66
+ raise Code::Error, "#{path} is not a regular file" unless File.file?(path)
67
+
68
+ File.open(path, "rb") do |file|
69
+ data = file.read(Code::MAX_INPUT_BYTES + 1).to_s
70
+ Code.ensure_input_size!(data, label: path)
71
+ data
72
+ end
73
+ end
74
+
75
+ def read_stdin
76
+ data = $stdin.read(Code::MAX_INPUT_BYTES + 1).to_s
77
+ Code.ensure_input_size!(data, label: "stdin")
78
+ data
79
+ end
80
+
81
+ def expand_arguments(arguments)
82
+ expanded_files = []
83
+ remaining_arguments = []
46
84
 
47
- parsed.arguments.each do |argument|
48
- if glob_pattern?(argument)
49
- matches = Dir.glob(argument).select { |path| File.file?(path) }
85
+ arguments.each do |argument|
86
+ if glob_pattern?(argument)
87
+ matches = Dir.glob(argument).select { |path| File.file?(path) }
50
88
 
51
- if matches.any?
52
- expanded_argument_files.concat(matches)
89
+ if matches.any?
90
+ expanded_files.concat(matches)
91
+ else
92
+ remaining_arguments << argument
93
+ end
53
94
  else
54
95
  remaining_arguments << argument
55
96
  end
56
- else
57
- remaining_arguments << argument
97
+
98
+ raise Code::Error, "too many input files" if expanded_files.size > MAX_ARGUMENT_FILES
58
99
  end
100
+
101
+ [expanded_files, remaining_arguments]
59
102
  end
60
103
 
61
- input = parsed.options.input.to_s
62
- input += File.read(input) if File.exist?(input)
63
- input += remaining_arguments.join(" ")
64
- input +=
65
- (parsed.files + expanded_argument_files)
66
- .map { |file| File.read(file) }
67
- .join("\n\n")
104
+ begin
105
+ @parsed_timeout = Code.normalize_timeout!(
106
+ parsed.options.timeout || Code::DEFAULT_TIMEOUT
107
+ )
108
+ rescue Code::Error => e
109
+ abort "#{e.class}: #{e.message}"
110
+ end
111
+
112
+ begin
113
+ input =
114
+ with_timeout do
115
+ buffer = +""
116
+ option_input = parsed.options.input.to_s
117
+ expanded_argument_files, remaining_arguments =
118
+ expand_arguments(parsed.arguments)
119
+
120
+ if option_input.present? && File.exist?(option_input)
121
+ append_limited(buffer, read_file(option_input))
122
+ else
123
+ append_limited(buffer, option_input)
124
+ end
125
+
126
+ append_limited(buffer, remaining_arguments.join(" "))
127
+
128
+ input_files = parsed.files + expanded_argument_files
129
+ raise Code::Error, "too many input files" if input_files.size > MAX_ARGUMENT_FILES
130
+
131
+ input_files.each.with_index do |file, index|
132
+ append_limited(buffer, "\n\n") if index.positive?
133
+ append_limited(buffer, read_file(file), label: file)
134
+ end
135
+
136
+ buffer
137
+ end
138
+ rescue Code::Error => e
139
+ abort "#{e.class}: #{e.message}"
140
+ end
68
141
 
69
142
  profile = parsed.options.profile || parsed.options.profiler
70
143
  require "ruby-prof" if profile
71
144
 
72
145
  RubyProf.start if profile
73
146
 
74
- input = $stdin.each_line.to_a.join if input.empty?
147
+ begin
148
+ input = with_timeout { read_stdin } if input.empty?
149
+ rescue Code::Error => e
150
+ abort "#{e.class}: #{e.message}"
151
+ end
75
152
 
76
153
  if parsed.options.parse
77
154
  begin
78
- pp Code::Parser.parse(input).to_raw
155
+ pp Code.parse(input, timeout: timeout)
79
156
  rescue StandardError => e
80
157
  warn e.message
81
158
  end
82
159
  elsif parsed.options.format
83
160
  begin
84
- print(Code.format(input, timeout: parsed.options.timeout))
161
+ print(Code.format(input, timeout: timeout))
85
162
  rescue Code::Error => e
86
163
  warn "#{e.class}: #{e.message}"
87
164
  end
@@ -93,7 +170,7 @@ else
93
170
  output: $stdout,
94
171
  error: $stderr,
95
172
  input: $stdin,
96
- timeout: parsed.options.timeout
173
+ timeout: timeout
97
174
  )
98
175
  )
99
176
  rescue Code::Error => e
@@ -3,14 +3,122 @@
3
3
  class Code
4
4
  module Concerns
5
5
  module Shared
6
- attr_accessor :raw, :methods
6
+ attr_accessor :raw, :functions
7
+
8
+ COMPOUND_ASSIGNMENT_OPERATORS = [
9
+ "+=",
10
+ "-=",
11
+ "*=",
12
+ "/=",
13
+ "%=",
14
+ "<<=",
15
+ ">>=",
16
+ "&=",
17
+ "|=",
18
+ "^=",
19
+ "||=",
20
+ "&&="
21
+ ].freeze
22
+ SHARED_OPERATORS = [
23
+ "documentation",
24
+ "present?",
25
+ "blank?",
26
+ "presence",
27
+ "presence_in",
28
+ "is_a?",
29
+ "is_an?",
30
+ "kind_of?",
31
+ "instance_of?",
32
+ "new",
33
+ "!",
34
+ "not",
35
+ "!=",
36
+ "different",
37
+ "&&",
38
+ "and",
39
+ "+",
40
+ "self",
41
+ "..",
42
+ "inclusive_range",
43
+ "...",
44
+ "exclusive_range",
45
+ "==",
46
+ "equal",
47
+ "equal?",
48
+ "same_object?",
49
+ ">",
50
+ "greater",
51
+ ">=",
52
+ "greater_or_equal",
53
+ "<=>",
54
+ "compare",
55
+ "<",
56
+ "less",
57
+ "<=",
58
+ "less_or_equal",
59
+ "===",
60
+ "strict_equal",
61
+ "!==",
62
+ "strict_different",
63
+ "falsy?",
64
+ "truthy?",
65
+ "true?",
66
+ "false?",
67
+ "||",
68
+ "or",
69
+ "to_boolean",
70
+ "to_class",
71
+ "to_date",
72
+ "to_decimal",
73
+ "to_dictionary",
74
+ "to_duration",
75
+ "to_integer",
76
+ "to_list",
77
+ "to_nothing",
78
+ "to_range",
79
+ "to_string",
80
+ "inspect",
81
+ "to_time",
82
+ "as_json",
83
+ "duplicate",
84
+ "deep_duplicate",
85
+ "to_parameter",
86
+ "to_json",
87
+ "functions",
88
+ "instance_functions",
89
+ "class_functions",
90
+ "respond_to?",
91
+ "send",
92
+ "itself",
93
+ "tap",
94
+ "then",
95
+ "name",
96
+ "nothing?",
97
+ "something?"
98
+ ].freeze
99
+ OPERATOR_METHOD_ALIASES = {
100
+ "[]" => "get",
101
+ "at" => "get",
102
+ "length" => "size",
103
+ "member?" => "include?",
104
+ "key?" => "has_key?",
105
+ "value?" => "has_value?",
106
+ "filter" => "select",
107
+ "filter!" => "select!"
108
+ }.freeze
7
109
 
8
110
  def call(**args)
9
111
  code_operator = args.fetch(:operator, nil).to_code
10
112
  code_arguments = args.fetch(:arguments, []).to_code
11
113
  code_value = code_arguments.code_first
12
114
 
115
+ dynamic_result = code_dynamic_call(code_operator, **args)
116
+ return dynamic_result if dynamic_result
117
+
13
118
  case code_operator.to_s
119
+ when "documentation"
120
+ sig(args)
121
+ code_documentation
14
122
  when "present?"
15
123
  sig(args)
16
124
  code_present?
@@ -23,6 +131,12 @@ class Code
23
131
  when "presence_in"
24
132
  sig(args) { Object::List }
25
133
  code_presence_in(code_value)
134
+ when "is_a?", "is_an?", "kind_of?"
135
+ sig(args) { Object::Class }
136
+ code_is_a?(code_value)
137
+ when "instance_of?"
138
+ sig(args) { Object::Class }
139
+ code_instance_of?(code_value)
26
140
  when "new"
27
141
  sig(args) { Object.repeat }
28
142
  code_new(*code_arguments.raw)
@@ -44,13 +158,16 @@ class Code
44
158
  when "...", "exclusive_range"
45
159
  sig(args) { Object }
46
160
  code_exclusive_range(code_value)
47
- when "==", "equal"
161
+ when "==", "equal", "equal?"
48
162
  sig(args) { Object }
49
163
  code_equal(code_value)
50
- when ">", "greater_or_equal"
164
+ when "same_object?"
165
+ sig(args) { Object }
166
+ code_same_object?(code_value)
167
+ when ">", "greater"
51
168
  sig(args) { Object }
52
169
  code_greater(code_value)
53
- when ">=", "greater"
170
+ when ">=", "greater_or_equal"
54
171
  sig(args) { Object }
55
172
  code_greater_or_equal(code_value)
56
173
  when "<=>", "compare"
@@ -74,6 +191,12 @@ class Code
74
191
  when "truthy?"
75
192
  sig(args)
76
193
  code_truthy?
194
+ when "true?"
195
+ sig(args)
196
+ code_true?
197
+ when "false?"
198
+ sig(args)
199
+ code_false?
77
200
  when "||", "or"
78
201
  sig(args) { Object }
79
202
  code_or(code_value)
@@ -136,9 +259,30 @@ class Code
136
259
  else
137
260
  code_to_json
138
261
  end
139
- when "methods"
262
+ when "functions"
263
+ sig(args)
264
+ code_functions
265
+ when "instance_functions"
140
266
  sig(args)
141
- code_methods
267
+ code_instance_functions
268
+ when "class_functions"
269
+ sig(args)
270
+ code_class_functions
271
+ when "respond_to?"
272
+ sig(args) { Object }
273
+ code_respond_to?(code_value)
274
+ when "send"
275
+ sig(args) { [Object, Object.repeat] }
276
+ code_send(*code_arguments.raw, **args)
277
+ when "itself"
278
+ sig(args)
279
+ code_itself
280
+ when "tap"
281
+ sig(args) { Object::Function }
282
+ code_tap(code_value, **args)
283
+ when "then"
284
+ sig(args) { Object::Function }
285
+ code_then(code_value, **args)
142
286
  when "name"
143
287
  sig(args)
144
288
  code_name
@@ -154,6 +298,9 @@ class Code
154
298
  if code_operator.to_s == "="
155
299
  code_context = args.fetch(:context)
156
300
  code_context.code_set(self, code_value)
301
+ elsif setter_operator?(code_operator)
302
+ code_dynamic_functions.code_set(code_operator.to_s.chop, code_value)
303
+ return code_value
157
304
  else
158
305
  code_context = args.fetch(:context).code_lookup!(self)
159
306
  code_context.code_set(
@@ -336,7 +483,7 @@ class Code
336
483
  self.class.new(self)
337
484
  end
338
485
 
339
- def code_deep_duplicate
486
+ def code_deep_duplicate(_seen = {})
340
487
  self.class.new(self)
341
488
  end
342
489
 
@@ -352,16 +499,30 @@ class Code
352
499
  Object::Nothing.new
353
500
  end
354
501
 
355
- def code_fetch(...)
356
- Object::Nothing.new
502
+ def code_fetch(key)
503
+ code_dynamic_functions.code_fetch(key)
357
504
  end
358
505
 
359
- def code_set(...)
360
- Object::Nothing.new
506
+ def code_set(key, value)
507
+ code_dynamic_functions.code_set(key, value)
361
508
  end
362
509
 
363
- def code_get(...)
364
- Object::Nothing.new
510
+ def code_get(key)
511
+ code_dynamic_functions.code_get(key)
512
+ end
513
+
514
+ def code_has_key?(key)
515
+ code_dynamic_functions.code_has_key?(key)
516
+ end
517
+
518
+ def code_dynamic_call(operator, **args)
519
+ return nil unless code_dynamic_functions.code_has_key?(operator).truthy?
520
+
521
+ stored_value = code_dynamic_functions.code_fetch(operator)
522
+ return stored_value.call(**args, operator: nil, bound_self: self) if stored_value.is_a?(Object::Function)
523
+
524
+ sig(args)
525
+ stored_value
365
526
  end
366
527
 
367
528
  def code_to_parameter
@@ -404,6 +565,14 @@ class Code
404
565
  Object::Boolean.new(truthy?)
405
566
  end
406
567
 
568
+ def code_true?
569
+ Object::Boolean.new(self == Object::Boolean.new(true))
570
+ end
571
+
572
+ def code_false?
573
+ Object::Boolean.new(self == Object::Boolean.new(false) || nothing?)
574
+ end
575
+
407
576
  def code_to_boolean
408
577
  Object::Boolean.new(self)
409
578
  end
@@ -460,8 +629,83 @@ class Code
460
629
  Object::String.new(name.to_s.split("::")[2..].join("::"))
461
630
  end
462
631
 
463
- def code_methods
464
- Object::List.new(methods)
632
+ def code_documentation
633
+ Object.documentation_for(self.class)
634
+ end
635
+
636
+ def code_functions
637
+ Object.sorted_dictionary(
638
+ code_instance_functions.code_merge(code_class_functions).raw
639
+ )
640
+ end
641
+
642
+ def code_instance_functions
643
+ Object.sorted_dictionary(
644
+ Object.documented_functions_for(self.class, :instance).code_merge(
645
+ dynamic_functions_documentation
646
+ ).raw
647
+ )
648
+ end
649
+
650
+ def code_class_functions
651
+ dynamic_functions_documentation
652
+ end
653
+
654
+ def code_respond_to?(operator)
655
+ code_operator = operator.to_code
656
+
657
+ Object::Boolean.new(code_respond_to_operator?(code_operator))
658
+ end
659
+
660
+ def code_is_a?(klass)
661
+ code_klass = klass.to_code
662
+
663
+ Object::Boolean.new(is_a?(code_klass.raw))
664
+ end
665
+
666
+ def code_instance_of?(klass)
667
+ code_klass = klass.to_code
668
+
669
+ Object::Boolean.new(instance_of?(code_klass.raw))
670
+ end
671
+
672
+ def code_same_object?(other)
673
+ code_other = other.to_code
674
+
675
+ Object::Boolean.new(equal?(code_other))
676
+ end
677
+
678
+ def code_itself
679
+ self
680
+ end
681
+
682
+ def code_send(operator, *arguments, **globals)
683
+ code_operator = operator.to_code
684
+
685
+ call(
686
+ **globals,
687
+ arguments: Object::List.new(arguments),
688
+ operator: code_operator
689
+ )
690
+ end
691
+
692
+ def code_tap(function, **globals)
693
+ code_function = function.to_code
694
+ code_function.call(
695
+ **globals,
696
+ arguments: Object::List.new([self]),
697
+ operator: nil
698
+ )
699
+ self
700
+ end
701
+
702
+ def code_then(function, **globals)
703
+ code_function = function.to_code
704
+ code_function.call(
705
+ **globals,
706
+ arguments: Object::List.new([self]),
707
+ operator: nil
708
+ )
465
709
  end
466
710
 
467
711
  def present?
@@ -489,6 +733,78 @@ class Code
489
733
 
490
734
  code_list.code_include?(self).truthy? ? self : Object::Nothing.new
491
735
  end
736
+
737
+ def code_documentable_functions
738
+ Object::Dictionary.new(
739
+ code_dynamic_functions.raw.merge(dictionary_attributes)
740
+ )
741
+ end
742
+
743
+ private
744
+
745
+ def setter_operator?(operator)
746
+ !COMPOUND_ASSIGNMENT_OPERATORS.include?(operator.to_s)
747
+ end
748
+
749
+ def code_respond_to_operator?(operator)
750
+ operator_name = operator.to_s
751
+
752
+ SHARED_OPERATORS.include?(operator_name) ||
753
+ code_operator_method_defined?(operator_name) ||
754
+ code_functions.code_has_key?(operator).truthy?
755
+ end
756
+
757
+ def code_operator_method_defined?(operator_name)
758
+ method_name = :"code_#{OPERATOR_METHOD_ALIASES.fetch(operator_name, operator_name)}"
759
+ return false unless respond_to?(method_name)
760
+
761
+ method(method_name).owner != Shared
762
+ end
763
+
764
+ def code_dynamic_functions
765
+ @functions = Object::Dictionary.new if @functions.blank?
766
+
767
+ @functions
768
+ end
769
+
770
+ def dynamic_functions_documentation
771
+ Object.sorted_dictionary(
772
+ code_documentable_functions.raw.to_h do |key, value|
773
+ name = key.to_s
774
+ [
775
+ name,
776
+ Object::Dictionary.new(
777
+ "name" => Object::String.new(name),
778
+ "description" => Object::String.new(
779
+ dynamic_function_description(value)
780
+ ),
781
+ "examples" => Object::List.new(dynamic_function_examples(value)),
782
+ "function" => value
783
+ )
784
+ ]
785
+ end
786
+ )
787
+ end
788
+
789
+ def dictionary_attributes
790
+ return {} unless is_a?(Object::Dictionary)
791
+
792
+ raw
793
+ end
794
+
795
+ def dynamic_function_description(value)
796
+ code_value = value.to_code
797
+ return "" unless code_value.is_a?(Object::Function)
798
+
799
+ code_value.documentation.code_get("description").to_s
800
+ end
801
+
802
+ def dynamic_function_examples(value)
803
+ code_value = value.to_code
804
+ return [] unless code_value.is_a?(Object::Function)
805
+
806
+ code_value.documentation.code_get("examples").to_code.code_to_list.raw
807
+ end
492
808
  end
493
809
  end
494
810
  end
data/lib/code/format.rb CHANGED
@@ -207,13 +207,17 @@ class Code
207
207
  end
208
208
 
209
209
  def escape_string_text(text)
210
- text.gsub("\\", "\\\\").gsub('"', '\"').gsub("{", "\\{")
210
+ text
211
+ .gsub("\\", "\\\\")
212
+ .gsub('"', '\"')
213
+ .gsub("{", "\\{")
211
214
  end
212
215
 
213
216
  def format_string_literal(content, components:, indent:, allow_split:)
214
217
  literal = %("#{content}")
215
218
  return literal if literal.length <= string_inline_limit(indent)
216
219
  return literal unless allow_split
220
+ return literal if content.include?("\\")
217
221
 
218
222
  split_string_literal(components, indent: indent)
219
223
  end
@@ -380,6 +384,14 @@ class Code
380
384
  return format_code_inline(Array(argument), indent: 0)
381
385
  end
382
386
 
387
+ if argument.key?(:operator)
388
+ return argument[:operator].to_s unless argument.key?(:value)
389
+
390
+ value = format_code_inline(argument[:value], indent: 0)
391
+
392
+ return "#{argument[:operator]}#{value}"
393
+ end
394
+
383
395
  value = format_code_inline(argument[:value], indent: 0)
384
396
  return value unless argument.key?(:name)
385
397
 
@@ -423,6 +435,8 @@ class Code
423
435
  parameter[:spread]
424
436
  elsif parameter.key?(:block)
425
437
  parameter[:block]
438
+ elsif parameter.key?(:blocks)
439
+ parameter[:blocks]
426
440
  else
427
441
  ""
428
442
  end