flor 0.9.5 → 0.10.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 (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
+