eggshell 0.8.3 → 1.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.
- checksums.yaml +4 -4
- data/bin/eggshell +13 -0
- data/lib/eggshell/block-handler.rb +161 -23
- data/lib/eggshell/block.rb +3 -2
- data/lib/eggshell/bundles/basics-old.rb +850 -0
- data/lib/eggshell/bundles/basics.rb +650 -589
- data/lib/eggshell/bundles/loader.rb +6 -5
- data/lib/eggshell/expression-evaluator.rb +13 -3
- data/lib/eggshell/format-handler.rb +40 -0
- data/lib/eggshell/macro-handler.rb +16 -10
- data/lib/eggshell/parse-tree.rb +149 -0
- data/lib/eggshell/processor-context.rb +5 -18
- data/lib/eggshell/processor.rb +707 -0
- data/lib/eggshell.rb +42 -740
- metadata +10 -5
@@ -13,13 +13,14 @@ module Eggshell::Bundles::Loader
|
|
13
13
|
end
|
14
14
|
|
15
15
|
class LoaderMacro
|
16
|
+
include Eggshell::MacroHandler
|
16
17
|
def set_processor(proc)
|
17
18
|
@proc = proc
|
18
|
-
proc.
|
19
|
+
proc.add_macro_handler(self, *%w(gems files bundles vars))
|
19
20
|
end
|
20
21
|
|
21
|
-
def process(
|
22
|
-
if
|
22
|
+
def process(type, args, lines, out, call_depth = 0)
|
23
|
+
if type == 'gems'
|
23
24
|
args.each do |gemname|
|
24
25
|
begin
|
25
26
|
require gemname
|
@@ -28,7 +29,7 @@ module Eggshell::Bundles::Loader
|
|
28
29
|
@proc._warn("could not load gem: #{gemname}")
|
29
30
|
end
|
30
31
|
end
|
31
|
-
elsif
|
32
|
+
elsif type == 'files'
|
32
33
|
args.each do |file|
|
33
34
|
begin
|
34
35
|
if file[0] == '/'
|
@@ -45,7 +46,7 @@ module Eggshell::Bundles::Loader
|
|
45
46
|
@proc._warn("could not load file: #{file}")
|
46
47
|
end
|
47
48
|
end
|
48
|
-
elsif
|
49
|
+
elsif type == 'bundles'
|
49
50
|
args.each do |bundle|
|
50
51
|
Eggshell::Bundles::Registry.attach_bundle(bundle, @proc.vars[:target])
|
51
52
|
end
|
@@ -5,6 +5,7 @@ class Eggshell::ExpressionEvaluator
|
|
5
5
|
REGEX_EXPR_PLACEHOLDERS = /(\\|\$\[|\$\{|\]|\}|\+|\-|>|<|=|\s+|\(|\)|\*|\/`)/
|
6
6
|
REGEX_EXPR_STATEMENT = /(\(|\)|,|\[|\]|\+|-|\*|\/|%|<=|>=|==|<|>|"|'|\s+|\\|\{|\}|:|\?)/
|
7
7
|
REGEX_OPERATORS = /\+|-|\*|\/|%|<=|>=|<|>|==|!=|&&|\|\||&|\|/
|
8
|
+
REGEX_VARNAME = /[\w\d]+/
|
8
9
|
|
9
10
|
LOG_OP = 2
|
10
11
|
LOG_LEVEL = 0
|
@@ -345,12 +346,19 @@ class Eggshell::ExpressionEvaluator
|
|
345
346
|
term = nil
|
346
347
|
term_state = nil
|
347
348
|
elsif tok == '{'
|
348
|
-
if state[-1] == :nil
|
349
|
+
if state[-1] == :nil #&& stack[0][-1][0] == :fn
|
349
350
|
delim = '{'
|
350
351
|
while toks[i]
|
351
352
|
delim += toks[i]
|
352
353
|
i += 1
|
353
354
|
end
|
355
|
+
|
356
|
+
# @todo is it safe to do stack[0]? stick to ptr instead?
|
357
|
+
if term
|
358
|
+
stack[0] << term_val(term, term_state == :quote)
|
359
|
+
term = nil
|
360
|
+
term_state = nil
|
361
|
+
end
|
354
362
|
stack[0] << [:brace_op, delim]
|
355
363
|
break
|
356
364
|
end
|
@@ -494,7 +502,8 @@ class Eggshell::ExpressionEvaluator
|
|
494
502
|
# look-ahead to build variable reference
|
495
503
|
ntok = toks[i]
|
496
504
|
while ntok
|
497
|
-
if ntok != ',' && ntok != ':' && ntok != '(' && ntok != ')' && ntok != '}' && !ntok.match(REGEX_OPERATORS)
|
505
|
+
#if ntok != ',' && ntok != ':' && ntok != '(' && ntok != ')' && ntok != '}' && ntok != '{' && !ntok.match(REGEX_OPERATORS)
|
506
|
+
if ntok.match(REGEX_VARNAME)
|
498
507
|
if ntok != ' ' && ntok != "\t"
|
499
508
|
term += ntok
|
500
509
|
end
|
@@ -506,7 +515,7 @@ class Eggshell::ExpressionEvaluator
|
|
506
515
|
end
|
507
516
|
end
|
508
517
|
end
|
509
|
-
|
518
|
+
|
510
519
|
# @todo validate completeness of state (e.g. no omitted parenthesis)
|
511
520
|
if state[1] || term
|
512
521
|
_transition.call(state[-1])
|
@@ -690,6 +699,7 @@ class Eggshell::ExpressionEvaluator
|
|
690
699
|
def self.expr_eval_op(op, lterm, rterm)
|
691
700
|
ret = nil
|
692
701
|
#$stderr.write "** #{lterm.inspect} ( #{op} ) #{rterm.inspect}\n"
|
702
|
+
|
693
703
|
case op
|
694
704
|
when '=='
|
695
705
|
ret = lterm == rterm
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# Interface for handling inline formatting. Markup follows this general structure:
|
2
|
+
# {{open_delim + string + close_delim}}. Opening and closing delimiters are defined
|
3
|
+
# by the handler.
|
4
|
+
module Eggshell::FormatHandler
|
5
|
+
def set_processor(proc, opts = nil)
|
6
|
+
@eggopts = opts || {}
|
7
|
+
@eggshell = proc
|
8
|
+
@eggshell.add_format_handler(self, @fmt_delimeters)
|
9
|
+
if self.respond_to?(:post_processor)
|
10
|
+
post_processor
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
# @param String tag The opening delimeter.
|
15
|
+
# @param String str The string between delimeters.
|
16
|
+
def format(tag, str)
|
17
|
+
end
|
18
|
+
|
19
|
+
module Utils
|
20
|
+
# Parses arguments in the form: `arg0 ; arg1 ; ...|att=val|att2=val|...`
|
21
|
+
#
|
22
|
+
# The first portion is the direct argument. For instance, a link like
|
23
|
+
# `[~ link ; text ~]` or an image like `[! src ; alt !]`. The remaining
|
24
|
+
# piped args are key-value pairs (use `\\|` to escape) which might
|
25
|
+
# be embedded in the tag or signal some further transformations.
|
26
|
+
#
|
27
|
+
# @return An array where the last element is always a {{Hash}}
|
28
|
+
def parse_args(arg_str)
|
29
|
+
raw_args = arg_str.split(/(?<!\\)\|/)
|
30
|
+
args = raw_args.shift.split(/ ; /)
|
31
|
+
map = {}
|
32
|
+
raw_args.each do |rarg|
|
33
|
+
k, v = rarg.split('=', 2)
|
34
|
+
map[k] = v
|
35
|
+
end
|
36
|
+
args << map
|
37
|
+
args
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -17,24 +17,30 @@
|
|
17
17
|
# misc content
|
18
18
|
# @end_block_macro
|
19
19
|
#
|
20
|
-
#
|
21
20
|
module Eggshell::MacroHandler
|
22
|
-
|
23
|
-
|
21
|
+
include Eggshell::BaseHandler
|
22
|
+
include Eggshell::ProcessHandler
|
23
|
+
|
24
|
+
|
25
|
+
COLLECT_NORMAL = :collect_normal
|
26
|
+
COLLECT_RAW_MACRO = :collect_raw_macro
|
27
|
+
COLLECT_RAW = :collect_raw
|
24
28
|
|
25
|
-
|
29
|
+
# Indicates how to process lines contained with in the macro. {{COLLECT_NORMAL}}
|
30
|
+
# continues to evaluate block and macro content. {{COLLECT_RAW_MACRO}} collects
|
31
|
+
# all lines as raw unless a macro is encountered. {{COLLECT_RAW}} collects all
|
32
|
+
# lines as raw, regardless of nested macros.
|
33
|
+
# @todo needed?
|
34
|
+
def collection_type(macro)
|
35
|
+
COLLECT_NORMAL
|
26
36
|
end
|
27
37
|
|
28
38
|
module Defaults
|
29
39
|
class NoOpHandler
|
30
40
|
include Eggshell::MacroHandler
|
31
41
|
|
32
|
-
def
|
33
|
-
@
|
34
|
-
end
|
35
|
-
|
36
|
-
def process(buffer, macname, args, lines, indent)
|
37
|
-
@proc._warn("couldn't find macro: #{macname}")
|
42
|
+
def process(name, args, lines, out, call_depth = 0)
|
43
|
+
@eggshell._warn("not implemented: #{macname}")
|
38
44
|
end
|
39
45
|
end
|
40
46
|
end
|
@@ -0,0 +1,149 @@
|
|
1
|
+
# Holds a hierarchical collection of blocks and macros. The tree follows
|
2
|
+
# this structure:
|
3
|
+
#
|
4
|
+
# pre. [
|
5
|
+
# String*,
|
6
|
+
# [:block, 'block_name', [], line_start]* # last entry is array of Eggshell::Line,
|
7
|
+
# [:macro, 'macro_name', {}, [
|
8
|
+
# __repeat_of_parse_tree
|
9
|
+
# ]
|
10
|
+
# ], line_start*
|
11
|
+
# ]
|
12
|
+
class Eggshell::ParseTree
|
13
|
+
BH = Eggshell::BlockHandler
|
14
|
+
|
15
|
+
IDX_TYPE = 0
|
16
|
+
IDX_NAME = 1
|
17
|
+
IDX_ARGS = 2
|
18
|
+
IDX_LINES = 3
|
19
|
+
IDX_LINES_START = 4
|
20
|
+
IDX_LINES_END = 5
|
21
|
+
|
22
|
+
def initialize
|
23
|
+
#@eggshell = eggshell
|
24
|
+
@modes = [:nil]
|
25
|
+
@tree = []
|
26
|
+
@lines = []
|
27
|
+
@macro_delims = []
|
28
|
+
@macro_open = []
|
29
|
+
@macro_ptr = []
|
30
|
+
@ptr = @tree
|
31
|
+
end
|
32
|
+
|
33
|
+
def new_macro(line_obj, line_start)
|
34
|
+
line = line_obj.line
|
35
|
+
macro, args, delim = Eggshell::Processor.parse_macro_start(line)
|
36
|
+
|
37
|
+
push_block
|
38
|
+
|
39
|
+
if delim
|
40
|
+
@modes << :macro
|
41
|
+
@macro_delims << delim.reverse.gsub('[', ']').gsub('(', ')').gsub('{', '}')
|
42
|
+
@macro_open << line
|
43
|
+
@macro_ptr << @ptr
|
44
|
+
# set ptr to entry's tree
|
45
|
+
entry = [:macro, macro, args, [], line_start]
|
46
|
+
@ptr << entry
|
47
|
+
@ptr = entry[IDX_LINES]
|
48
|
+
else
|
49
|
+
@ptr << [:macro, macro, args, [], line_start]
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def macro_delim_match(line_obj, line_num)
|
54
|
+
if @macro_delims[-1] == line_obj.line
|
55
|
+
if @modes[-1] == :block
|
56
|
+
push_block
|
57
|
+
end
|
58
|
+
@macro_delims.pop
|
59
|
+
@macro_open.pop
|
60
|
+
@ptr = @macro_ptr.pop
|
61
|
+
@ptr[-1] << line_num
|
62
|
+
last_mode = @modes.pop
|
63
|
+
return true
|
64
|
+
end
|
65
|
+
return false
|
66
|
+
end
|
67
|
+
|
68
|
+
def new_block(handler, type, line_obj, consume_mode, line_start)
|
69
|
+
block_type, args, line = Eggshell::Processor.parse_block_start(line_obj.line)
|
70
|
+
nline = Eggshell::Line.new(line, line_obj.tab_str, line_obj.indent_lvl, line_obj.line_num)
|
71
|
+
|
72
|
+
if consume_mode != BH::DONE
|
73
|
+
@modes << :block
|
74
|
+
if line != ''
|
75
|
+
@lines << nline
|
76
|
+
line_start -= 1
|
77
|
+
end
|
78
|
+
@cur_block = [handler, type, args, line_start]
|
79
|
+
if consume_mode == BH::COLLECT_RAW
|
80
|
+
mode = :raw
|
81
|
+
else consume_mode == BH::COLLECT
|
82
|
+
mode = :block
|
83
|
+
end
|
84
|
+
else
|
85
|
+
@ptr << [:block, type, args, [nline], line_start]
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def push_block
|
90
|
+
if @modes[-1] == :block
|
91
|
+
if @cur_block
|
92
|
+
line_end = @cur_block[3]
|
93
|
+
line_end = @lines[-1].line_num if @lines[-1]
|
94
|
+
@ptr << [:block, @cur_block[1], @cur_block[2], @lines, @cur_block[3], line_end]
|
95
|
+
@lines = []
|
96
|
+
@cur_block[0].reset
|
97
|
+
@cur_block = nil
|
98
|
+
end
|
99
|
+
@modes.pop
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def collect(line_obj)
|
104
|
+
more = @cur_block[0].continue_with(line_obj.line)
|
105
|
+
if more != BH::RETRY
|
106
|
+
@lines << line_obj
|
107
|
+
if more == BH::DONE
|
108
|
+
push_block
|
109
|
+
end
|
110
|
+
else
|
111
|
+
push_block
|
112
|
+
end
|
113
|
+
more
|
114
|
+
end
|
115
|
+
|
116
|
+
def raw_line(line_obj)
|
117
|
+
@ptr << line_obj
|
118
|
+
end
|
119
|
+
|
120
|
+
def tree
|
121
|
+
@tree.clone
|
122
|
+
end
|
123
|
+
|
124
|
+
# @todo return macro_open
|
125
|
+
|
126
|
+
def mode
|
127
|
+
@modes[-1]
|
128
|
+
end
|
129
|
+
|
130
|
+
# Does basic output of parse tree structure to visually inspect parsed info.
|
131
|
+
def self.walk(struct = nil, indent = 0, out = nil)
|
132
|
+
out = $stdout if !out
|
133
|
+
struct.each do |row|
|
134
|
+
if row.is_a?(Eggshell::Line)
|
135
|
+
out.write "#{' '*indent}#{row.to_s.inspect} ##{row.line_num}\n"
|
136
|
+
elsif row.is_a?(Array)
|
137
|
+
if row[0] == :macro
|
138
|
+
out.write "#{' '*indent}@#{row[1]}(#{row[2].inspect}) | end=#{row[-1]}\n"
|
139
|
+
walk(row[3], indent + 1, out)
|
140
|
+
elsif row[0] == :block
|
141
|
+
out.write "#{' '*indent}#{row[1]}(#{row[2].inspect}) | end=#{row[-1]}\n"
|
142
|
+
walk(row[3], indent + 1, out)
|
143
|
+
end
|
144
|
+
else
|
145
|
+
out.write "#{' '*indent}#{row.inspect} ?\n"
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
@@ -1,28 +1,15 @@
|
|
1
1
|
# Holds things like variables, line/char count, and other useful information for a {{Processor}} instance.
|
2
2
|
class Eggshell::ProcessorContext
|
3
3
|
def initialize
|
4
|
-
@vars = {:references => {}, :toc => [], :include_paths => [], 'log.level' =>
|
4
|
+
@vars = {:references => {}, :toc => [], :include_paths => [], 'log.level' => 1}
|
5
5
|
@funcs = {}
|
6
6
|
@macros = {}
|
7
|
-
@blocks =
|
7
|
+
@blocks = []
|
8
|
+
@blocks_map = {}
|
8
9
|
@block_params = {}
|
9
10
|
@expr_cache = {}
|
10
|
-
|
11
|
-
# keeps track of line counters based on include
|
12
|
-
@lcounters = [Eggshell::LineCounter.new]
|
11
|
+
@fmt_handlers = {}
|
13
12
|
end
|
14
13
|
|
15
|
-
attr_reader :vars, :funcs, :macros, :blocks, :block_params, :expr_cache
|
16
|
-
|
17
|
-
def push_line_counter
|
18
|
-
@lcounters << Eggshell::LineCounter.new
|
19
|
-
end
|
20
|
-
|
21
|
-
def pop_line_counter
|
22
|
-
@lcounters.pop
|
23
|
-
end
|
24
|
-
|
25
|
-
def line_counter
|
26
|
-
@lcounters[-1]
|
27
|
-
end
|
14
|
+
attr_reader :vars, :funcs, :macros, :blocks, :blocks_map, :block_params, :expr_cache, :fmt_handlers
|
28
15
|
end
|