eggshell 1.0.3 → 1.1.1
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/bin/eggshell +2 -1
- data/lib/eggshell.rb +6 -0
- data/lib/eggshell/block-handler.rb +20 -0
- data/lib/eggshell/bundles/basic-functions.rb +31 -0
- data/lib/eggshell/bundles/basics.rb +192 -39
- data/lib/eggshell/compiler.rb +452 -0
- data/lib/eggshell/expression-evaluator.rb +246 -832
- data/lib/eggshell/expression-evaluator/evaluator.rb +45 -0
- data/lib/eggshell/expression-evaluator/lexer.rb +473 -0
- data/lib/eggshell/expression-evaluator/parser.rb +422 -0
- data/lib/eggshell/macro-handler.rb +13 -1
- data/lib/eggshell/parse-tree.rb +62 -11
- data/lib/eggshell/processor.rb +48 -70
- data/lib/eggshell/stream.rb +43 -0
- metadata +8 -2
data/lib/eggshell/processor.rb
CHANGED
@@ -1,10 +1,13 @@
|
|
1
1
|
module Eggshell
|
2
2
|
class Processor
|
3
|
-
BLOCK_MATCH = /^([a-z0-9_-]
|
4
|
-
BLOCK_MATCH_PARAMS = /^([a-z0-9_-]
|
3
|
+
BLOCK_MATCH = /^([a-zA-Z_][a-z0-9_-]*\.)/
|
4
|
+
BLOCK_MATCH_PARAMS = /^([a-zA-Z_][a-z0-9_-]*)\s*\(/
|
5
|
+
|
6
|
+
@@ee = Eggshell::ExpressionEvaluator.new
|
5
7
|
|
6
|
-
def initialize
|
7
|
-
@context =
|
8
|
+
def initialize(context = nil)
|
9
|
+
@context = context
|
10
|
+
@context = Eggshell::ProcessorContext.new if !context.is_a?(Eggshell::ProcessorContext)
|
8
11
|
@vars = @context.vars
|
9
12
|
@funcs = @context.funcs
|
10
13
|
@macros = @context.macros
|
@@ -14,6 +17,9 @@ module Eggshell
|
|
14
17
|
@expr_cache = @context.expr_cache
|
15
18
|
@fmt_handlers = @context.fmt_handlers
|
16
19
|
@ee = Eggshell::ExpressionEvaluator.new(@vars, @funcs)
|
20
|
+
|
21
|
+
@vars[:include_paths] = [] if !@vars[:include_paths]
|
22
|
+
@vars[:include_paths] << File.realdirpath(Dir.pwd())
|
17
23
|
|
18
24
|
@noop_macro = Eggshell::MacroHandler::Defaults::NoOpHandler.new
|
19
25
|
@noop_block = Eggshell::BlockHandler::Defaults::NoOpHandler.new
|
@@ -29,6 +35,10 @@ module Eggshell
|
|
29
35
|
end
|
30
36
|
end
|
31
37
|
|
38
|
+
def get_block_handler(name)
|
39
|
+
@blocks_map[name]
|
40
|
+
end
|
41
|
+
|
32
42
|
def rem_block_handler(*names)
|
33
43
|
_trace "rem_block_handler: #{names.inspect}"
|
34
44
|
names.each do |name|
|
@@ -44,6 +54,10 @@ module Eggshell
|
|
44
54
|
end
|
45
55
|
end
|
46
56
|
|
57
|
+
def get_macro_handler(name)
|
58
|
+
@macros[name]
|
59
|
+
end
|
60
|
+
|
47
61
|
def rem_macro_handler(*names)
|
48
62
|
_trace "rem_macro_handler: #{names.inspect}"
|
49
63
|
names.each do |name|
|
@@ -51,17 +65,8 @@ module Eggshell
|
|
51
65
|
end
|
52
66
|
end
|
53
67
|
|
54
|
-
|
55
|
-
|
56
|
-
# a specific set of functions within the namespace. The root namespace is a blank string.
|
57
|
-
#
|
58
|
-
# @param String func_key In the form `ns` or `ns:func_name`. For functions in the
|
59
|
-
# root namespace, do `:func_name`.
|
60
|
-
# @param Object handler
|
61
|
-
# @param Array func_names If `func_key` only refers to a namespace but the handler
|
62
|
-
# needs to only handle a subset of functions, supply the list of function names here.
|
63
|
-
def register_functions(func_key, handler, func_names = nil)
|
64
|
-
@ee.register_functions(func_key, handler, func_names)
|
68
|
+
def register_functions(handler, names = nil, ns = '')
|
69
|
+
@ee.register_functions(handler, names, ns)
|
65
70
|
end
|
66
71
|
|
67
72
|
def _error(msg)
|
@@ -90,7 +95,7 @@ module Eggshell
|
|
90
95
|
attr_reader :vars
|
91
96
|
|
92
97
|
def expr_eval(struct)
|
93
|
-
return
|
98
|
+
return @ee.evaluate(struct)
|
94
99
|
end
|
95
100
|
|
96
101
|
# Expands expressions (`\${}`) and macro calls (`\@@macro\@@`).
|
@@ -135,7 +140,7 @@ module Eggshell
|
|
135
140
|
struct = @expr_cache[expr_str]
|
136
141
|
|
137
142
|
if !struct
|
138
|
-
struct =
|
143
|
+
struct = @ee.parse(expr_str)
|
139
144
|
@expr_cache[expr_str] = struct
|
140
145
|
end
|
141
146
|
|
@@ -188,41 +193,6 @@ module Eggshell
|
|
188
193
|
TAB = "\t"
|
189
194
|
TAB_SPACE = ' '
|
190
195
|
|
191
|
-
# @param Boolean is_default If true, associates these parameters with the
|
192
|
-
# `block_type` used in `get_block_param()` or explicitly in third parameter.
|
193
|
-
# @param String block_type
|
194
|
-
def set_block_params(params, is_default = false, block_type = nil)
|
195
|
-
if block_type && is_default
|
196
|
-
@block_params[block_type] = params
|
197
|
-
else
|
198
|
-
@block_params[:pending] = params
|
199
|
-
@block_param_default = is_default
|
200
|
-
end
|
201
|
-
end
|
202
|
-
|
203
|
-
# Gets the block parameters for a block type, and merges default values if available.
|
204
|
-
def get_block_params(block_type)
|
205
|
-
bp = @block_params.delete(:pending)
|
206
|
-
if @block_params_default
|
207
|
-
if block_type && bp
|
208
|
-
@block_params[block_type] = bp if bp
|
209
|
-
end
|
210
|
-
@block_params_default = false
|
211
|
-
bp = {} if !bp
|
212
|
-
else
|
213
|
-
bp = {} if !bp
|
214
|
-
default = @block_params[block_type]
|
215
|
-
if default
|
216
|
-
default.each do |key,val|
|
217
|
-
if !bp.has_key?(key) && val
|
218
|
-
bp[key] = val.clone
|
219
|
-
end
|
220
|
-
end
|
221
|
-
end
|
222
|
-
end
|
223
|
-
return bp
|
224
|
-
end
|
225
|
-
|
226
196
|
# Sets the default output object. Must support {{<<}} and {{join(String)}}.
|
227
197
|
#
|
228
198
|
# If {{out}} is a `Class`, must support empty initialization.
|
@@ -337,11 +307,18 @@ module Eggshell
|
|
337
307
|
stat = parse_tree.collect(line_norm)
|
338
308
|
next if stat != BH::RETRY
|
339
309
|
parse_tree.push_block
|
310
|
+
elsif parse_tree.mode == :macro_raw
|
311
|
+
if !parse_tree.macro_delim_match(line_norm, line_count)
|
312
|
+
parse_tree.collect_macro_raw(line_norm)
|
313
|
+
end
|
314
|
+
next
|
340
315
|
end
|
341
316
|
|
342
317
|
# macro processing
|
343
318
|
if line[0] == '@'
|
344
|
-
|
319
|
+
macro, args, delim = parse_macro_start(line)
|
320
|
+
mhandler = get_macro_handler(macro)
|
321
|
+
parse_tree.new_macro(line_norm, line_count, macro, args, delim, mhandler ? mhandler.collection_type(macro) : nil)
|
345
322
|
next
|
346
323
|
elsif parse_tree.macro_delim_match(line_norm, line_count)
|
347
324
|
next
|
@@ -367,7 +344,7 @@ module Eggshell
|
|
367
344
|
stat = handler.can_handle(line)
|
368
345
|
next if stat == BH::RETRY
|
369
346
|
|
370
|
-
parse_tree.new_block(handler, handler.current_type, line_norm, stat, line_count)
|
347
|
+
parse_tree.new_block(handler, handler.current_type, line_norm, stat, line_count, self)
|
371
348
|
found = true
|
372
349
|
_trace "(#{handler.current_type}->#{handler}) #{line} -> #{stat}"
|
373
350
|
break
|
@@ -375,7 +352,7 @@ module Eggshell
|
|
375
352
|
|
376
353
|
if !found
|
377
354
|
@blocks_map['p'].can_handle('p.')
|
378
|
-
parse_tree.new_block(@blocks_map['p'], 'p', line_norm, BH::COLLECT, line_count)
|
355
|
+
parse_tree.new_block(@blocks_map['p'], 'p', line_norm, BH::COLLECT, line_count, self)
|
379
356
|
end
|
380
357
|
end
|
381
358
|
parse_tree.push_block
|
@@ -417,11 +394,11 @@ module Eggshell
|
|
417
394
|
joiner = opts[:join] || "\n"
|
418
395
|
|
419
396
|
parse_tree = parse_tree.tree if parse_tree.is_a?(Eggshell::ParseTree)
|
420
|
-
raise Exception.new("input not an array or ParseTree (depth=#{call_depth}") if !parse_tree.is_a?(Array)
|
421
|
-
|
422
|
-
|
397
|
+
raise Exception.new("input not an array or ParseTree (depth=#{call_depth})") if !parse_tree.is_a?(Array)
|
398
|
+
|
423
399
|
last_type = nil
|
424
400
|
last_line = 0
|
401
|
+
last_macro = nil
|
425
402
|
deferred = nil
|
426
403
|
|
427
404
|
parse_tree.each do |unit|
|
@@ -445,13 +422,12 @@ module Eggshell
|
|
445
422
|
args_o = unit[2] || []
|
446
423
|
args = []
|
447
424
|
args_o.each do |arg|
|
448
|
-
args <<
|
425
|
+
args << (arg.is_a?(Array) ? @@ee.evaluate([:array, arg]) : arg)
|
449
426
|
end
|
450
|
-
|
427
|
+
|
451
428
|
lines = unit[ParseTree::IDX_LINES]
|
452
429
|
lines_start = unit[ParseTree::IDX_LINES_START]
|
453
430
|
lines_end = unit[ParseTree::IDX_LINES_END]
|
454
|
-
|
455
431
|
_handler, _name, _args, _lines = deferred
|
456
432
|
|
457
433
|
if unit[0] == :block
|
@@ -522,7 +498,7 @@ module Eggshell
|
|
522
498
|
|
523
499
|
def process(lines, line_count = 0, call_depth = 0)
|
524
500
|
parse_tree = preprocess(lines, line_count)
|
525
|
-
assemble(parse_tree.tree, call_depth)
|
501
|
+
assemble(Eggshell::ParseTree.condense(self, parse_tree.tree), call_depth)
|
526
502
|
end
|
527
503
|
|
528
504
|
# Register inline format handlers with opening and closing tags.
|
@@ -612,21 +588,22 @@ module Eggshell
|
|
612
588
|
buff.join('')
|
613
589
|
end
|
614
590
|
|
615
|
-
def
|
591
|
+
def parse_block_start(line)
|
616
592
|
block_type = nil
|
617
593
|
args = []
|
618
594
|
|
619
595
|
bt = line.match(BLOCK_MATCH_PARAMS)
|
620
596
|
if bt
|
621
597
|
idx0 = bt[0].length
|
622
|
-
idx1 = line.index(')
|
598
|
+
idx1 = line.index(')', idx0)
|
623
599
|
if idx1
|
624
600
|
block_type = line[0..idx0-2]
|
625
601
|
params = line[0...idx1+1].strip
|
626
602
|
line = line[idx1+2..line.length] || ''
|
627
603
|
if params != ''
|
628
|
-
struct =
|
604
|
+
struct = @ee.parse(params)
|
629
605
|
args = struct[0][2]
|
606
|
+
#args = @ee.evaluate([[:array, struct[0][2]]])
|
630
607
|
end
|
631
608
|
end
|
632
609
|
else
|
@@ -644,7 +621,7 @@ module Eggshell
|
|
644
621
|
[block_type, args, line]
|
645
622
|
end
|
646
623
|
|
647
|
-
def
|
624
|
+
def parse_macro_start(line)
|
648
625
|
macro = nil
|
649
626
|
args = []
|
650
627
|
delim = nil
|
@@ -652,11 +629,12 @@ module Eggshell
|
|
652
629
|
# either macro is a plain '@macro' or it has parameters/opening brace
|
653
630
|
if line.index(' ') || line.index('(') || line.index('{')
|
654
631
|
# since the macro statement is essentially a function call, parse the line as an expression to get components
|
655
|
-
expr_struct =
|
632
|
+
expr_struct = @ee.parse(line)
|
656
633
|
fn = expr_struct.shift
|
657
|
-
|
658
|
-
|
659
|
-
|
634
|
+
|
635
|
+
if fn.is_a?(Array) && (fn[0] == :func || fn[0] == :var)
|
636
|
+
macro = fn[1]
|
637
|
+
args = fn[2] # @@ee.evaluate([:array, fn[2]])
|
660
638
|
if expr_struct[-1].is_a?(Array) && expr_struct[-1][0] == :brace_op
|
661
639
|
delim = expr_struct[-1][1]
|
662
640
|
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# Interfaces and helper classes to have processor-friendly streams.
|
2
|
+
module Eggshell; module Stream;
|
3
|
+
def <<(str)
|
4
|
+
end
|
5
|
+
|
6
|
+
def join(str)
|
7
|
+
end
|
8
|
+
|
9
|
+
def write(str)
|
10
|
+
end
|
11
|
+
|
12
|
+
def [](index)
|
13
|
+
end
|
14
|
+
|
15
|
+
class IOWrapper
|
16
|
+
include Stream
|
17
|
+
|
18
|
+
def initialize(stream)
|
19
|
+
@stream = stream
|
20
|
+
@buff = []
|
21
|
+
end
|
22
|
+
|
23
|
+
def <<(str)
|
24
|
+
@buff << str
|
25
|
+
end
|
26
|
+
|
27
|
+
def write(str)
|
28
|
+
@stream.write(str)
|
29
|
+
end
|
30
|
+
|
31
|
+
def join(str)
|
32
|
+
@buff.join(str)
|
33
|
+
end
|
34
|
+
|
35
|
+
def [](index)
|
36
|
+
@buff[index]
|
37
|
+
end
|
38
|
+
|
39
|
+
def flush
|
40
|
+
@stream.write(@buff.join("\n"))
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end; end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: eggshell
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kaiser Shahid
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-08-16 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: From fast and basic HTML to complex decouments and more, Eggshell aims
|
14
14
|
to provide you with all the document generation power you need through simple markup.
|
@@ -22,15 +22,21 @@ files:
|
|
22
22
|
- lib/eggshell/block-handler.rb
|
23
23
|
- lib/eggshell/block.rb
|
24
24
|
- lib/eggshell/bundles.rb
|
25
|
+
- lib/eggshell/bundles/basic-functions.rb
|
25
26
|
- lib/eggshell/bundles/basics-old.rb
|
26
27
|
- lib/eggshell/bundles/basics.rb
|
27
28
|
- lib/eggshell/bundles/loader.rb
|
29
|
+
- lib/eggshell/compiler.rb
|
28
30
|
- lib/eggshell/expression-evaluator.rb
|
31
|
+
- lib/eggshell/expression-evaluator/evaluator.rb
|
32
|
+
- lib/eggshell/expression-evaluator/lexer.rb
|
33
|
+
- lib/eggshell/expression-evaluator/parser.rb
|
29
34
|
- lib/eggshell/format-handler.rb
|
30
35
|
- lib/eggshell/macro-handler.rb
|
31
36
|
- lib/eggshell/parse-tree.rb
|
32
37
|
- lib/eggshell/processor-context.rb
|
33
38
|
- lib/eggshell/processor.rb
|
39
|
+
- lib/eggshell/stream.rb
|
34
40
|
homepage: https://acmedinotech.com/products/eggshell
|
35
41
|
licenses:
|
36
42
|
- MIT
|