flor 0.9.5 → 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (91) hide show
  1. data/CHANGELOG.md +10 -0
  2. data/Makefile +13 -5
  3. data/README.md +0 -35
  4. data/flor.gemspec +1 -0
  5. data/lib/flor.rb +6 -24
  6. data/lib/flor/changes.rb +26 -0
  7. data/lib/flor/colours.rb +65 -31
  8. data/lib/flor/conf.rb +84 -54
  9. data/lib/flor/core.rb +0 -23
  10. data/lib/flor/core/executor.rb +12 -42
  11. data/lib/flor/core/node.rb +19 -24
  12. data/lib/flor/core/procedure.rb +13 -24
  13. data/lib/flor/core/texecutor.rb +10 -28
  14. data/lib/flor/deep.rb +152 -0
  15. data/lib/flor/djan.rb +200 -0
  16. data/lib/flor/dollar.rb +0 -24
  17. data/lib/flor/errors.rb +0 -24
  18. data/lib/flor/flor.rb +43 -296
  19. data/lib/flor/id.rb +90 -0
  20. data/lib/flor/log.rb +12 -35
  21. data/lib/flor/migrations/0002_cunit_and_munit.rb +86 -0
  22. data/lib/flor/parser.rb +40 -46
  23. data/lib/flor/pcore/_arr.rb +0 -24
  24. data/lib/flor/pcore/_atom.rb +0 -24
  25. data/lib/flor/pcore/_att.rb +3 -25
  26. data/lib/flor/pcore/_dump.rb +0 -24
  27. data/lib/flor/pcore/_err.rb +0 -24
  28. data/lib/flor/pcore/_happly.rb +0 -24
  29. data/lib/flor/pcore/_obj.rb +0 -24
  30. data/lib/flor/pcore/_skip.rb +0 -24
  31. data/lib/flor/pcore/arith.rb +0 -24
  32. data/lib/flor/pcore/break.rb +0 -24
  33. data/lib/flor/pcore/case.rb +127 -0
  34. data/lib/flor/pcore/cmp.rb +0 -24
  35. data/lib/flor/pcore/cond.rb +24 -24
  36. data/lib/flor/pcore/cursor.rb +0 -24
  37. data/lib/flor/pcore/define.rb +0 -24
  38. data/lib/flor/pcore/fail.rb +0 -24
  39. data/lib/flor/pcore/if.rb +39 -0
  40. data/lib/flor/pcore/loop.rb +0 -24
  41. data/lib/flor/pcore/map.rb +0 -24
  42. data/lib/flor/pcore/match.rb +0 -24
  43. data/lib/flor/pcore/move.rb +0 -24
  44. data/lib/flor/pcore/noeval.rb +0 -24
  45. data/lib/flor/pcore/noret.rb +0 -24
  46. data/lib/flor/pcore/push.rb +1 -25
  47. data/lib/flor/pcore/rand.rb +59 -0
  48. data/lib/flor/pcore/sequence.rb +0 -24
  49. data/lib/flor/pcore/set.rb +0 -24
  50. data/lib/flor/pcore/stall.rb +0 -24
  51. data/lib/flor/pcore/until.rb +0 -24
  52. data/lib/flor/pcore/val.rb +0 -24
  53. data/lib/flor/punit/cancel.rb +0 -24
  54. data/lib/flor/punit/cmap.rb +0 -24
  55. data/lib/flor/punit/concurrence.rb +54 -24
  56. data/lib/flor/punit/every.rb +0 -24
  57. data/lib/flor/punit/graft.rb +41 -0
  58. data/lib/flor/punit/on.rb +0 -24
  59. data/lib/flor/punit/schedule.rb +0 -24
  60. data/lib/flor/punit/signal.rb +0 -24
  61. data/lib/flor/punit/sleep.rb +0 -24
  62. data/lib/flor/punit/task.rb +0 -26
  63. data/lib/flor/punit/trace.rb +0 -24
  64. data/lib/flor/punit/trap.rb +0 -24
  65. data/lib/flor/to_string.rb +4 -25
  66. data/lib/flor/tools/env.rb +0 -23
  67. data/lib/flor/tools/shell.rb +810 -0
  68. data/lib/flor/unit.rb +0 -23
  69. data/lib/flor/unit/executor.rb +35 -31
  70. data/lib/flor/unit/ganger.rb +9 -34
  71. data/lib/flor/unit/hooker.rb +5 -25
  72. data/lib/flor/unit/journal.rb +0 -23
  73. data/lib/flor/unit/loader.rb +63 -94
  74. data/lib/flor/unit/logger.rb +8 -27
  75. data/lib/flor/unit/models.rb +0 -24
  76. data/lib/flor/unit/models/execution.rb +13 -24
  77. data/lib/flor/unit/models/pointer.rb +0 -24
  78. data/lib/flor/unit/models/timer.rb +0 -24
  79. data/lib/flor/unit/models/trace.rb +0 -24
  80. data/lib/flor/unit/models/trap.rb +0 -24
  81. data/lib/flor/unit/scheduler.rb +157 -128
  82. data/lib/flor/unit/storage.rb +224 -167
  83. data/lib/flor/unit/taskers.rb +38 -25
  84. data/lib/flor/unit/waiter.rb +7 -26
  85. data/lib/flor/unit/wlist.rb +8 -24
  86. metadata +28 -7
  87. data/fail.txt +0 -16
  88. data/intercepted.txt +0 -123
  89. data/lib/flor/pcore/ife.rb +0 -56
  90. data/lib/flor/tools/repl.rb +0 -231
  91. data/out.txt +0 -206
@@ -1,26 +1,3 @@
1
- #--
2
- # Copyright (c) 2015-2017, John Mettraux, jmettraux+flor@gmail.com
3
- #
4
- # Permission is hereby granted, free of charge, to any person obtaining a copy
5
- # of this software and associated documentation files (the "Software"), to deal
6
- # in the Software without restriction, including without limitation the rights
7
- # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
- # copies of the Software, and to permit persons to whom the Software is
9
- # furnished to do so, subject to the following conditions:
10
- #
11
- # The above copyright notice and this permission notice shall be included in
12
- # all copies or substantial portions of the Software.
13
- #
14
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
- # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20
- # THE SOFTWARE.
21
- #
22
- # Made in Japan.
23
- #++
24
1
 
25
2
  module Flor
26
3
 
@@ -1,27 +1,3 @@
1
- #--
2
- # Copyright (c) 2015-2017, John Mettraux, jmettraux+flor@gmail.com
3
- #
4
- # Permission is hereby granted, free of charge, to any person obtaining a copy
5
- # of this software and associated documentation files (the "Software"), to deal
6
- # in the Software without restriction, including without limitation the rights
7
- # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
- # copies of the Software, and to permit persons to whom the Software is
9
- # furnished to do so, subject to the following conditions:
10
- #
11
- # The above copyright notice and this permission notice shall be included in
12
- # all copies or substantial portions of the Software.
13
- #
14
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
- # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20
- # THE SOFTWARE.
21
- #
22
- # Made in Japan.
23
- #++
24
-
25
1
 
26
2
  module Flor
27
3
 
@@ -173,23 +149,7 @@ module Flor
173
149
 
174
150
  node['heat0'] = tree[0]
175
151
  node['heat'] = heat = n.deref(t0)
176
-
177
- node['heap'] = heap =
178
- if ! heat.is_a?(Array)
179
- '_val'
180
- elsif tree && tree[1] == []
181
- '_val'
182
- elsif heat[0] == '_proc'
183
- heat[1]['proc']
184
- elsif heat[0] == '_func'
185
- 'apply'
186
- elsif heat[0] == '_task'
187
- 'task'
188
- elsif Flor.is_tree_head_tree?(tree)
189
- '_happly'
190
- else
191
- '_val'
192
- end
152
+ node['heap'] = heap = n.reheap(tree, heat)
193
153
 
194
154
  if heap == 'task' && heat[0] == '_task'
195
155
  #
@@ -357,8 +317,16 @@ module Flor
357
317
 
358
318
  def task(message)
359
319
 
320
+ return error_reply(
321
+ node(message['nid']),
322
+ message,
323
+ "don't know how to apply #{message['tasker'].inspect}"
324
+ ) if message['routed'] == false
325
+
360
326
  @execution['tasks'][message['nid']] =
361
327
  { 'tasker' => message['tasker'], 'name' => message['taskname'] }
328
+ #
329
+ # FIXME is it in use???
362
330
 
363
331
  @unit.ganger.task(self, message)
364
332
  end
@@ -367,6 +335,8 @@ module Flor
367
335
  def return(message)
368
336
 
369
337
  @execution['tasks'].delete(message['nid'])
338
+ #
339
+ # FIXME is it in use???
370
340
 
371
341
  [
372
342
  { 'point' => 'receive',
@@ -398,7 +368,7 @@ module Flor
398
368
  ms = []
399
369
  ms += @unit.notify(self, message) # pre
400
370
 
401
- ms += self.send(message['point'].to_sym, message)
371
+ ms += self.send(message['point'], message)
402
372
 
403
373
  message['payload'] = message.delete('pld') if message.has_key?('pld')
404
374
  message['consumed'] = Flor.tstamp
@@ -1,27 +1,3 @@
1
- #--
2
- # Copyright (c) 2015-2017, John Mettraux, jmettraux+flor@gmail.com
3
- #
4
- # Permission is hereby granted, free of charge, to any person obtaining a copy
5
- # of this software and associated documentation files (the "Software"), to deal
6
- # in the Software without restriction, including without limitation the rights
7
- # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
- # copies of the Software, and to permit persons to whom the Software is
9
- # furnished to do so, subject to the following conditions:
10
- #
11
- # The above copyright notice and this permission notice shall be included in
12
- # all copies or substantial portions of the Software.
13
- #
14
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
- # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20
- # THE SOFTWARE.
21
- #
22
- # Made in Japan.
23
- #++
24
-
25
1
 
26
2
  class Flor::Node
27
3
 
@@ -233,6 +209,25 @@ class Flor::Node
233
209
  v
234
210
  end
235
211
 
212
+ def reheap(tree, heat)
213
+
214
+ if ! heat.is_a?(Array)
215
+ '_val'
216
+ elsif tree && tree[1] == []
217
+ '_val'
218
+ elsif heat[0] == '_proc'
219
+ heat[1]['proc']
220
+ elsif heat[0] == '_func'
221
+ 'apply'
222
+ elsif heat[0] == '_task'
223
+ 'task'
224
+ elsif Flor.is_tree_head_tree?(tree)
225
+ '_happly'
226
+ else
227
+ '_val'
228
+ end
229
+ end
230
+
236
231
  def tree
237
232
 
238
233
  lookup_tree(nid)
@@ -1,27 +1,3 @@
1
- #--
2
- # Copyright (c) 2015-2017, John Mettraux, jmettraux+flor@gmail.com
3
- #
4
- # Permission is hereby granted, free of charge, to any person obtaining a copy
5
- # of this software and associated documentation files (the "Software"), to deal
6
- # in the Software without restriction, including without limitation the rights
7
- # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
- # copies of the Software, and to permit persons to whom the Software is
9
- # furnished to do so, subject to the following conditions:
10
- #
11
- # The above copyright notice and this permission notice shall be included in
12
- # all copies or substantial portions of the Software.
13
- #
14
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
- # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20
- # THE SOFTWARE.
21
- #
22
- # Made in Japan.
23
- #++
24
-
25
1
 
26
2
  class Flor::Procedure < Flor::Node
27
3
 
@@ -284,6 +260,14 @@ class Flor::Procedure < Flor::Node
284
260
 
285
261
  @node['mtime'] = Flor.tstamp
286
262
 
263
+ orl.each do |m|
264
+
265
+ m['from'] = @node['parent'] if m['from'] == 'parent'
266
+
267
+ #m['payload'] ||= Flor.dup(@node['payload'])
268
+ # No, let re_applier supply payload
269
+ end
270
+
287
271
  orl
288
272
  end
289
273
 
@@ -485,6 +469,8 @@ class Flor::Procedure < Flor::Node
485
469
  cni = fun[1]['cnid'] # closure nid
486
470
 
487
471
  t = lookup_tree(fni)
472
+ fail ArgumentError.new("couldn't find function at #{fni}") unless t
473
+
488
474
  t = t[0] if fun[1]['head']
489
475
 
490
476
  sig = t[1].select { |c| c[0] == '_att' }
@@ -537,6 +523,9 @@ class Flor::Procedure < Flor::Node
537
523
 
538
524
  return kill if @message['flavour'] == 'kill'
539
525
 
526
+ orl = @message['on_receive_last']
527
+ @node['on_receive_last'] = orl if orl
528
+
540
529
  return cancel_when_ended if node_ended?
541
530
  return cancel_when_closed if node_closed?
542
531
 
@@ -1,27 +1,3 @@
1
- #--
2
- # Copyright (c) 2015-2017, John Mettraux, jmettraux+flor@gmail.com
3
- #
4
- # Permission is hereby granted, free of charge, to any person obtaining a copy
5
- # of this software and associated documentation files (the "Software"), to deal
6
- # in the Software without restriction, including without limitation the rights
7
- # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
- # copies of the Software, and to permit persons to whom the Software is
9
- # furnished to do so, subject to the following conditions:
10
- #
11
- # The above copyright notice and this permission notice shall be included in
12
- # all copies or substantial portions of the Software.
13
- #
14
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
- # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20
- # THE SOFTWARE.
21
- #
22
- # Made in Japan.
23
- #++
24
-
25
1
 
26
2
  module Flor
27
3
 
@@ -182,10 +158,16 @@ module Flor
182
158
 
183
159
  def self.interpret(path)
184
160
 
185
- s = path
186
-
187
- s = File.read(s).strip unless s.match(/[\r\n]/)
188
- s = "{\n#{s}\n}"
161
+ s =
162
+ if path.match(/[\r\n]/)
163
+ path.strip
164
+ else
165
+ ls = File.readlines(path)
166
+ ls.reject! { |l| l.strip[0, 1] == '#' }
167
+ s = ls.join("\n").strip
168
+ end
169
+ s =
170
+ "{\n#{s}\n}" unless s[0, 1] == '{' && s[-1, 1] == '}'
189
171
 
190
172
  vs = Hash.new { |h, k| k }
191
173
  class << vs
@@ -0,0 +1,152 @@
1
+
2
+ module Flor
3
+
4
+ # deep.rb
5
+ #
6
+ # functions for deep getting/setting in structures
7
+
8
+ def self.to_array_index(o)
9
+
10
+ return 0 if o == 'first'
11
+ return -1 if o == 'last'
12
+ return o if o.is_a?(Integer)
13
+ nil
14
+ end
15
+
16
+ def self.split_deep_path(k)
17
+
18
+ return k if k.is_a?(Array)
19
+
20
+ k
21
+ .scan(/(?:\.?(-?\d+)|\.?([^\.\[]+)|\[(-?\d+)\]|\[([^\[\]]+)\])/)
22
+ .collect { |doti, dots, squi, squs|
23
+ if doti
24
+ doti.to_i
25
+ elsif dots
26
+ dots
27
+ elsif squi
28
+ squi.to_i
29
+ else
30
+ s0 = squs[0, 1]
31
+ (s0 == "'" || s0 == '"') ? squs[1..-2] : squs
32
+ end }
33
+ end
34
+
35
+ def self.deep_get(o, k) # --> success(boolean), value
36
+
37
+ return [ true, o ] unless k
38
+
39
+ val = o
40
+
41
+ split_deep_path(k).each do |kk|
42
+
43
+ case val
44
+ when Array
45
+ i = to_array_index(kk)
46
+ return [ false, nil ] unless i
47
+ val = val[i]
48
+ when Hash
49
+ val = val[kk]
50
+ else
51
+ return [ false, nil ]
52
+ end
53
+ end
54
+
55
+ [ true, val ]
56
+ end
57
+
58
+ def self.deep_set(o, k, v) # --> [ success(boolean), value ]
59
+
60
+ ks = split_deep_path(k)
61
+ key = ks.pop
62
+
63
+ b, col = deep_get(o, ks)
64
+
65
+ return [ false, v ] unless b
66
+
67
+ case col
68
+ when Array
69
+ i = to_array_index(key)
70
+ return [ false, v ] unless i
71
+ col[i] = v
72
+ when Hash
73
+ col[key] = v
74
+ else
75
+ return [ false, v ]
76
+ end
77
+
78
+ [ true, v ]
79
+ end
80
+
81
+ def self.deep_insert(o, k, v) # --> [ success(boolean), value ]
82
+
83
+ ks = split_deep_path(k)
84
+ key = ks.pop
85
+
86
+ b, col = deep_get(o, ks)
87
+
88
+ return [ false, nil ] unless b
89
+
90
+ case col
91
+ when Array
92
+ i = to_array_index(key)
93
+ return [ false, v ] unless i
94
+ col.insert(i, v)
95
+ when Hash
96
+ col[key] = v
97
+ else
98
+ return [ false, v ]
99
+ end
100
+
101
+ [ true, v ]
102
+ end
103
+
104
+ def self.deep_unset(o, k) # --> [ success(boolean), value ]
105
+
106
+ ks = split_deep_path(k)
107
+ key = ks.pop
108
+
109
+ b, col = deep_get(o, ks)
110
+
111
+ return [ false, nil ] unless b
112
+
113
+ v =
114
+ case col
115
+ when Array
116
+ i = to_array_index(key)
117
+ return [ false, nil ] unless i
118
+ col.delete_at(i)
119
+ when Hash
120
+ col.delete(key)
121
+ else
122
+ return [ false, nil ]
123
+ end
124
+
125
+ [ true, v ]
126
+ end
127
+
128
+ def self.deep_has_key?(o, k)
129
+
130
+ val = o
131
+ ks = split_deep_path(k)
132
+
133
+ loop do
134
+
135
+ kk = ks.shift
136
+
137
+ case val
138
+ when Array
139
+ i = to_array_index(kk)
140
+ return false unless i
141
+ return (i < 0 ? -i < val.length : i < val.length) if ks.empty?
142
+ val = val[i]
143
+ when Hash
144
+ return val.has_key?(kk) if ks.empty?
145
+ val = val[kk]
146
+ else
147
+ return false
148
+ end
149
+ end
150
+ end
151
+ end
152
+
@@ -0,0 +1,200 @@
1
+
2
+ require 'io/console'
3
+
4
+
5
+ module Flor
6
+
7
+ def self.to_djan(x, opts={}); to_d(x, opts); end
8
+
9
+ def self.to_d(x, opts={})
10
+
11
+ opts[:s] = StringIO.new
12
+ opts[:c] = Flor.colours(opts)
13
+
14
+ if opts[:width] == true
15
+ opts[:width] = IO.console.winsize[1]
16
+ elsif mw = (opts[:mw] || opts[:maxwidth] || opts[:max_width])
17
+ opts[:width] = [ IO.console.winsize[1], mw ].min
18
+ end
19
+
20
+ Djan.to_d(x, opts)
21
+
22
+ opts[:s].string
23
+ end
24
+
25
+ module Djan
26
+ extend self
27
+
28
+ def to_d(x, opts)
29
+
30
+ case x
31
+ when nil then nil_to_d(x, opts)
32
+ when String then string_to_d(x, opts)
33
+ when Hash then object_to_d(x, opts)
34
+ when Array then array_to_d(x, opts)
35
+ when TrueClass then boolean_to_d(x.to_s, opts)
36
+ when FalseClass then boolean_to_d(x.to_s, opts)
37
+ else num_to_d(x.to_s, opts)
38
+ end
39
+ end
40
+
41
+ def len(x, opts)
42
+
43
+ opts = opts.merge(
44
+ s: StringIO.new, c: Flor.no_colours, indent: nil, width: nil)
45
+
46
+ to_d(x, opts)
47
+
48
+ opts[:s].string.length
49
+ end
50
+
51
+ def newline(opts)
52
+
53
+ opts[:s] << "\n"
54
+ end
55
+
56
+ def space(opts, force=false)
57
+
58
+ opts[:s] << ' ' if force || ! opts[:compact]
59
+ end
60
+
61
+ def newline_or_space(opts)
62
+
63
+ if opts[:indent]
64
+ newline(opts)
65
+ elsif ! opts[:compact]
66
+ space(opts)
67
+ end
68
+ end
69
+
70
+ def indent_space(opts)
71
+
72
+ return if opts.delete(:first)
73
+ i = opts[:indent]
74
+ opts[:s] << ' ' * i if i
75
+ end
76
+
77
+ def indent(opts, os={})
78
+
79
+ if i = opts[:indent]
80
+ opts.merge(indent: i + (os[:inc] || 1), first: os[:first])
81
+ else
82
+ opts
83
+ end
84
+ end
85
+
86
+ def adjust(x, opts)
87
+
88
+ i = opts[:indent]
89
+ w = opts[:width]
90
+
91
+ return opts unless i && w && i + len(x, opts) < w
92
+ opts.merge(indent: nil)
93
+ end
94
+
95
+ def object_to_d(x, opts)
96
+
97
+ inner = opts.delete(:inner)
98
+
99
+ indent_space(opts)
100
+
101
+ return c_inf('{}', opts) if x.empty?
102
+
103
+ opts = adjust(x, opts)
104
+
105
+ unless inner
106
+ c_inf('{', opts); space(opts)
107
+ end
108
+
109
+ x.each_with_index do |(k, v), i|
110
+ string_to_d(k, indent(opts, first: i == 0))
111
+ c_inf(':', opts)
112
+ newline_or_space(opts)
113
+ to_d(v, indent(opts, inc: 2))
114
+ if i < x.size - 1
115
+ c_inf(',', opts)
116
+ newline_or_space(opts)
117
+ end
118
+ end
119
+
120
+ unless inner
121
+ space(opts); c_inf('}', opts)
122
+ end
123
+ end
124
+
125
+ def array_to_d(x, opts)
126
+
127
+ inner = opts.delete(:inner)
128
+
129
+ indent_space(opts)
130
+
131
+ return c_inf('[]', opts) if x.empty?
132
+
133
+ opts = adjust(x, opts)
134
+
135
+ unless inner
136
+ c_inf('[', opts); space(opts)
137
+ end
138
+
139
+ x.each_with_index do |e, i|
140
+ to_d(e, indent(opts, first: i == 0))
141
+ if i < x.size - 1
142
+ c_inf(',', opts)
143
+ newline_or_space(opts)
144
+ end
145
+ end
146
+
147
+ unless inner
148
+ space(opts); c_inf(']', opts)
149
+ end
150
+ end
151
+
152
+ def string_to_d(x, opts)
153
+
154
+ x = x.to_s
155
+
156
+ indent_space(opts)
157
+
158
+ if (
159
+ x.match(/\A[^: \b\f\n\r\t"',()\[\]{}#\\]+\z/) == nil ||
160
+ x.to_i.to_s == x ||
161
+ x.to_f.to_s == x
162
+ )
163
+ c_inf('"', opts)
164
+ c_str(x.inspect[1..-2], opts)
165
+ c_inf('"', opts)
166
+ else
167
+ c_str(x, opts)
168
+ end
169
+ end
170
+
171
+ def boolean_to_d(x, opts)
172
+
173
+ indent_space(opts)
174
+ if x
175
+ c_tru(x, opts)
176
+ else
177
+ c_fal(x, opts)
178
+ end
179
+ end
180
+
181
+ def num_to_d(x, opts)
182
+
183
+ indent_space(opts); c_num(x, opts)
184
+ end
185
+
186
+ def nil_to_d(x, opts)
187
+
188
+ indent_space(opts); c_nil('null', opts)
189
+ end
190
+
191
+ def c_inf(s, opts); opts[:s] << opts[:c].dark_gray(s); end
192
+
193
+ def c_nil(s, opts); opts[:s] << opts[:c].dark_gray(s); end
194
+ def c_tru(s, opts); opts[:s] << opts[:c].green(s); end
195
+ def c_fal(s, opts); opts[:s] << opts[:c].red(s); end
196
+ def c_str(s, opts); opts[:s] << opts[:c].brown(s); end
197
+ def c_num(s, opts); opts[:s] << opts[:c].light_blue(s); end
198
+ end
199
+ end
200
+