glyph 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/AUTHORS.textile +1 -1
- data/CHANGELOG.textile +119 -222
- data/LICENSE.textile +1 -1
- data/README.textile +42 -23
- data/Rakefile +1 -3
- data/VERSION +1 -1
- data/benchmark.rb +72 -0
- data/book/config.yml +4 -4
- data/book/document.glyph +90 -57
- data/book/images/document_generation.png +0 -0
- data/book/lib/macros/reference.rb +75 -22
- data/book/output/html/glyph.html +3183 -2121
- data/book/output/html/images/document_generation.png +0 -0
- data/book/output/pdf/glyph.pdf +7370 -4913
- data/book/resources/document_generation.txt +34 -0
- data/book/snippets.yml +6 -0
- data/book/text/changelog.glyph +45 -34
- data/book/text/compiling/compiling.glyph +23 -0
- data/book/text/compiling/lite_mode.glyph +23 -0
- data/book/text/compiling/programmatic_usage.glyph +77 -0
- data/book/text/extending/bookmarks_headers.glyph +21 -0
- data/book/text/extending/further_reading.glyph +13 -0
- data/book/text/extending/internals.glyph +79 -0
- data/book/text/extending/interpreting.glyph +51 -0
- data/book/text/extending/macro_def.glyph +64 -0
- data/book/text/extending/params_attrs.glyph +70 -0
- data/book/text/extending/placeholders.glyph +34 -0
- data/book/text/extending/validators.glyph +16 -0
- data/book/text/getting_started/configuration.glyph +49 -0
- data/book/text/getting_started/create_project.glyph +41 -0
- data/book/text/getting_started/structure.glyph +55 -0
- data/book/text/introduction.glyph +49 -26
- data/book/text/license.glyph +1 -1
- data/book/text/macros/macros_block.glyph +99 -0
- data/book/text/macros/macros_core.glyph +208 -0
- data/book/text/macros/macros_filters.glyph +40 -0
- data/book/text/macros/macros_inline.glyph +50 -0
- data/book/text/macros/macros_structure.glyph +100 -0
- data/book/text/ref_commands.glyph +94 -73
- data/book/text/ref_config.glyph +34 -42
- data/book/text/ref_macros.glyph +1 -373
- data/book/text/text_editing/code.glyph +51 -0
- data/book/text/text_editing/conditionals.glyph +49 -0
- data/book/text/text_editing/evaluation.glyph +13 -0
- data/book/text/text_editing/glyph_files.glyph +7 -0
- data/book/text/text_editing/images.glyph +29 -0
- data/book/text/text_editing/inclusions.glyph +44 -0
- data/book/text/text_editing/links.glyph +53 -0
- data/book/text/text_editing/macro_intro.glyph +111 -0
- data/book/text/text_editing/raw_html.glyph +112 -0
- data/book/text/text_editing/sections.glyph +63 -0
- data/book/text/text_editing/stylesheets.glyph +36 -0
- data/book/text/troubleshooting/errors_command.glyph +39 -0
- data/book/text/troubleshooting/errors_generic.glyph +29 -0
- data/book/text/troubleshooting/errors_intro.glyph +3 -0
- data/book/text/troubleshooting/errors_macro.glyph +98 -0
- data/book/text/troubleshooting/errors_parser.glyph +29 -0
- data/config.yml +77 -58
- data/document.glyph +25 -25
- data/glyph.gemspec +57 -22
- data/lib/glyph.rb +54 -13
- data/lib/glyph/commands.rb +84 -17
- data/lib/glyph/config.rb +3 -3
- data/lib/glyph/document.rb +14 -8
- data/lib/glyph/interpreter.rb +18 -58
- data/lib/glyph/macro.rb +160 -55
- data/lib/glyph/macro_validators.rb +104 -12
- data/lib/glyph/node.rb +24 -0
- data/lib/glyph/parser.rb +278 -0
- data/lib/glyph/syntax_node.rb +225 -0
- data/macros/core.rb +212 -0
- data/macros/filters.rb +66 -15
- data/macros/html/block.rb +43 -105
- data/macros/html/inline.rb +11 -12
- data/macros/html/structure.rb +123 -58
- data/macros/xml.rb +33 -0
- data/spec/files/container.textile +2 -2
- data/spec/files/document.glyph +2 -2
- data/spec/files/document_with_toc.glyph +3 -3
- data/spec/files/included.textile +1 -1
- data/spec/files/ligature.jpg +0 -0
- data/spec/files/markdown.markdown +2 -1
- data/spec/lib/commands_spec.rb +46 -3
- data/spec/lib/document_spec.rb +4 -4
- data/spec/lib/glyph_spec.rb +17 -46
- data/spec/lib/interpreter_spec.rb +6 -25
- data/spec/lib/macro_spec.rb +141 -43
- data/spec/lib/macro_validators_spec.rb +27 -5
- data/spec/lib/node_spec.rb +26 -1
- data/spec/lib/parser_spec.rb +246 -0
- data/spec/lib/syntax_node_spec.rb +111 -0
- data/spec/macros/core_spec.rb +195 -0
- data/spec/macros/filters_spec.rb +38 -4
- data/spec/macros/macros_spec.rb +20 -176
- data/spec/macros/textile_spec.rb +13 -71
- data/spec/macros/xml_spec.rb +77 -0
- data/spec/spec_helper.rb +50 -10
- data/spec/tasks/load_spec.rb +13 -2
- data/styles/default.css +18 -6
- data/styles/pagination.css +1 -19
- data/tasks/generate.rake +2 -2
- data/tasks/load.rake +27 -17
- data/tasks/project.rake +1 -1
- metadata +75 -62
- data/book/script/compile.rb +0 -8
- data/book/script/prof +0 -1
- data/book/script/prof_results.htm +0 -21079
- data/book/text/authoring.glyph +0 -548
- data/book/text/extending.glyph +0 -224
- data/book/text/getting_started.glyph +0 -158
- data/book/text/troubleshooting.glyph +0 -179
- data/lib/glyph/glyph_language.rb +0 -538
- data/lib/glyph/glyph_language.treetop +0 -27
- data/macros/common.rb +0 -160
data/lib/glyph/config.rb
CHANGED
@@ -77,9 +77,9 @@ module Glyph
|
|
77
77
|
# @raise [ArgumentError] if the setting refers to an invalid namespace
|
78
78
|
# @example
|
79
79
|
# cfg = Glyph::Config.new
|
80
|
-
# cfg.set "quiet", true # Sets
|
80
|
+
# cfg.set "system.quiet", true # Sets "system.quiet" => true
|
81
81
|
# cfg.set "test.test_value", "[1,2,3]" # Sets :test => {:test_value => [1,2,3]}
|
82
|
-
# cfg.
|
82
|
+
# cfg.set "system.quiet", "false" # Sets "system.quiet" => false
|
83
83
|
def set(setting, value)
|
84
84
|
raise RuntimeError, "Configuration cannot be changed" unless @options[:mutable]
|
85
85
|
if value.is_a?(String) && value.match(/^(["'].*["']|:.+|\[.*\]|\{.*\}|true|false|nil)$/) then
|
@@ -122,7 +122,7 @@ module Glyph
|
|
122
122
|
# @see Glyph::Config#set
|
123
123
|
# @example
|
124
124
|
# cfg = Glyph::Config.new
|
125
|
-
# cfg.get
|
125
|
+
# cfg.get "system.quiet" # true
|
126
126
|
# cfg.get "test.test_value" # [1,2,3]
|
127
127
|
def get(setting)
|
128
128
|
@data.instance_eval "self#{setting.to_s.split(".").map{|key| "[:#{key}]" }.join}" rescue nil
|
data/lib/glyph/document.rb
CHANGED
@@ -6,7 +6,7 @@ module Glyph
|
|
6
6
|
# currently being interpreted.
|
7
7
|
#
|
8
8
|
# It is responsible of analyzing (evaluating) the syntax tree and return the corresponding output
|
9
|
-
# as well as
|
9
|
+
# as well as replacing placeholders.
|
10
10
|
class Document
|
11
11
|
|
12
12
|
ESCAPES = [
|
@@ -40,7 +40,7 @@ module Glyph
|
|
40
40
|
# @raise [RuntimeError] unless the document has been analized
|
41
41
|
def structure
|
42
42
|
raise RuntimeError, "Document has not been analyzed" unless analyzed? || finalized?
|
43
|
-
@tree
|
43
|
+
@tree
|
44
44
|
end
|
45
45
|
|
46
46
|
# Copies bookmarks, headers, todos and placeholders from another Glyph::Document
|
@@ -99,7 +99,7 @@ module Glyph
|
|
99
99
|
def analyze
|
100
100
|
raise RuntimeError, "Document is #{@state}" if analyzed? || finalized?
|
101
101
|
@context[:document] = self
|
102
|
-
@output = @tree.evaluate @context
|
102
|
+
@output = @tree.evaluate @context
|
103
103
|
@state = :analyzed
|
104
104
|
end
|
105
105
|
|
@@ -114,12 +114,18 @@ module Glyph
|
|
114
114
|
raise RuntimeError, "Document cannot be finalized due to previous errors" unless @context[:document].errors.blank?
|
115
115
|
# Substitute placeholders
|
116
116
|
ESCAPES.each{|e| @output.gsub! e[0], e[1]}
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
Glyph
|
117
|
+
begin
|
118
|
+
@placeholders.each_pair do |key, value|
|
119
|
+
begin
|
120
|
+
@output.gsub! key.to_s, value.call(self).to_s
|
121
|
+
rescue Glyph::MacroError => e
|
122
|
+
e.macro.macro_warning e.message, e
|
123
|
+
rescue Exception => e
|
124
|
+
puts e.class
|
125
|
+
Glyph.warning e.message
|
126
|
+
end
|
122
127
|
end
|
128
|
+
rescue Exception => e
|
123
129
|
end
|
124
130
|
@state = :finalized
|
125
131
|
end
|
data/lib/glyph/interpreter.rb
CHANGED
@@ -1,74 +1,24 @@
|
|
1
|
-
# @private
|
2
|
-
class GlyphSyntaxNode < Treetop::Runtime::SyntaxNode
|
3
|
-
|
4
|
-
attr_reader :data
|
5
|
-
|
6
|
-
def evaluate(context, current=nil)
|
7
|
-
current ||= context.to_node
|
8
|
-
@data ||= current.to_node
|
9
|
-
elements.map { |e| e.evaluate(context, current) if e.respond_to? :evaluate }.join
|
10
|
-
end
|
11
|
-
|
12
|
-
end
|
13
|
-
|
14
|
-
# @private
|
15
|
-
class MacroNode < GlyphSyntaxNode
|
16
|
-
|
17
|
-
def evaluate(context, current)
|
18
|
-
name = macro_name.text_value.to_sym
|
19
|
-
raise Glyph::SyntaxError, "Undefined macro '#{name}'\n -> source: #{current[:source]}" unless Glyph::MACROS.include? name
|
20
|
-
@data = {:macro => name, :source => context[:source], :document => context[:document]}.to_node
|
21
|
-
@data[:escape] = true if is_a? EscapingMacroNode
|
22
|
-
current << @data
|
23
|
-
@data[:value] = super(context, @data).strip
|
24
|
-
Glyph::Macro.new(@data).execute
|
25
|
-
end
|
26
|
-
|
27
|
-
end
|
28
|
-
|
29
|
-
# @private
|
30
|
-
class EscapingMacroNode < MacroNode; end
|
31
|
-
|
32
|
-
# @private
|
33
|
-
class TextNode < GlyphSyntaxNode
|
34
|
-
|
35
|
-
def evaluate(context, current=nil)
|
36
|
-
text_value
|
37
|
-
end
|
38
|
-
|
39
|
-
end
|
40
|
-
|
41
|
-
|
42
1
|
module Glyph
|
43
|
-
|
2
|
+
|
44
3
|
# A Glyph::Interpreter object perform the following actions:
|
45
4
|
# * Parses a string of text containing Glyph macros
|
46
5
|
# * Creates a document based on the parsed syntax tree
|
47
6
|
# * Analyzes and finalizes the document
|
48
7
|
class Interpreter
|
49
8
|
|
50
|
-
PARSER = GlyphLanguageParser.new
|
51
|
-
|
52
9
|
# Creates a new Glyph::Interpreter object.
|
53
10
|
# @param [String] text the string to interpret
|
54
|
-
# @param [Hash] context the context to pass along when
|
55
|
-
def initialize(text, context=
|
56
|
-
context ||= {:source => '--'}
|
57
|
-
@raw = PARSER.parse text
|
11
|
+
# @param [Hash] context the context to pass along when expanding macros
|
12
|
+
def initialize(text, context={})
|
58
13
|
@context = context
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
err = "#{reason}\n -> #{@context[:source]} [Line #{PARSER.failure_line}, Column #{PARSER.failure_column}]"
|
63
|
-
@context[:document].errors << err if @context[:document] && !@context[:embedded]
|
64
|
-
raise Glyph::SyntaxError, err
|
65
|
-
end
|
66
|
-
@document = Glyph::Document.new @raw, @context
|
67
|
-
@document.inherit_from @context[:document] if @context[:document]
|
14
|
+
@context[:source] ||= {:name => "--"}
|
15
|
+
@text = text
|
16
|
+
@parser = Glyph::Parser.new text, @context[:source][:name]
|
68
17
|
end
|
69
18
|
|
70
19
|
# @see Glyph::Document#analyze
|
71
20
|
def process
|
21
|
+
parse unless @tree
|
72
22
|
@document.analyze
|
73
23
|
end
|
74
24
|
|
@@ -80,15 +30,25 @@ module Glyph
|
|
80
30
|
# Returns the finalized @document (calls self#process and self#postprocess if necessary)
|
81
31
|
# @return [Glyph::Document] the finalized document
|
82
32
|
def document
|
33
|
+
parse unless @tree
|
83
34
|
return @document if @document.finalized?
|
84
35
|
process if @document.new?
|
85
36
|
postprocess if @document.analyzed?
|
86
37
|
@document
|
87
38
|
end
|
88
39
|
|
40
|
+
# Parses the string provided during initialization
|
41
|
+
# @return [Glyph::SyntaxNode] the Abstract Syntax Tree generated from the string
|
42
|
+
# @since 0.3.0
|
43
|
+
def parse
|
44
|
+
Glyph.info "Parsing: #{@context[:source][:name]}" if Glyph.debug? && @context[:info] && @context[:source][:name]
|
45
|
+
@tree = @parser.parse
|
46
|
+
@document = Glyph::Document.new @tree, @context
|
47
|
+
@document.inherit_from @context[:document] if @context[:document]
|
48
|
+
@tree
|
49
|
+
end
|
89
50
|
|
90
51
|
end
|
91
|
-
|
92
52
|
end
|
93
53
|
|
94
54
|
|
data/lib/glyph/macro.rb
CHANGED
@@ -9,41 +9,153 @@ module Glyph
|
|
9
9
|
|
10
10
|
include Validators
|
11
11
|
|
12
|
+
attr_reader :node, :source
|
13
|
+
|
12
14
|
# Creates a new macro instance from a Node
|
13
15
|
# @param [Node] node a node populated with macro data
|
14
16
|
def initialize(node)
|
15
17
|
@node = node
|
16
|
-
@name = @node[:
|
17
|
-
@
|
18
|
-
@source = @node[:source]
|
19
|
-
@escaped_pipe = '‡‡‡‡‡ESCAPED¤PIPE‡‡‡‡‡'
|
18
|
+
@name = @node[:name]
|
19
|
+
@updated_source = nil
|
20
|
+
@source = @node[:source][:name] rescue "--"
|
20
21
|
end
|
21
22
|
|
22
|
-
#
|
23
|
-
#
|
24
|
-
|
25
|
-
|
26
|
-
@
|
23
|
+
# Resets the name of the updated source (call before calling
|
24
|
+
# Macro#interpret)
|
25
|
+
# @param [String] name the source name
|
26
|
+
def update_source(name)
|
27
|
+
@updated_source = {:node => @node, :name => name}
|
28
|
+
end
|
29
|
+
|
30
|
+
# Returns a Glyph code representation of the specified parameter
|
31
|
+
# @param [Fixnum] n the index of the parameter
|
32
|
+
# @return [String, nil] the string representation of the parameter
|
33
|
+
# @since 0.3.0
|
34
|
+
def raw_parameter(n)
|
35
|
+
@node.parameter(n).contents.to_s rescue nil
|
36
|
+
end
|
37
|
+
|
38
|
+
# Returns a Glyph code representation of the specified attribute
|
39
|
+
# @param [String, Symbol] name the name of the attribute
|
40
|
+
# @return [String, nil] the string representation of the attribute
|
41
|
+
# @since 0.3.0
|
42
|
+
def raw_attribute(name)
|
43
|
+
@node.attribute(name).contents.to_s rescue nil
|
44
|
+
end
|
45
|
+
|
46
|
+
# Returns an evaluated macro attribute by name
|
47
|
+
# @param [String, Symbol] name the name of the attribute
|
48
|
+
# @param [Hash] options a hash of options
|
49
|
+
# @option options [Boolean] :strip whether the value is stripped or not
|
50
|
+
# @return [String, nil] the value of the attribute
|
51
|
+
# @since 0.3.0
|
52
|
+
def attribute(name, options={:strip => true})
|
53
|
+
return @attributes[name.to_sym] if @attributes && @attributes[name.to_sym]
|
54
|
+
return nil unless @node.attribute(name)
|
55
|
+
@attributes = {} unless @attributes
|
56
|
+
@attributes[name] = @node.attribute(name).evaluate(@node, :attrs => true).to_s
|
57
|
+
@attributes[name].strip! if options[:strip]
|
58
|
+
@attributes[name]
|
59
|
+
end
|
60
|
+
|
61
|
+
# Returns an evaluated macro parameter by index
|
62
|
+
# @param [Fixnum] n the index of the parameter
|
63
|
+
# @param [Hash] options a hash of options
|
64
|
+
# @option options [Boolean] :strip whether the value is stripped or not
|
65
|
+
# @return [String, nil] the value of the parameter
|
66
|
+
# @since 0.3.0
|
67
|
+
def parameter(n, options={:strip => true})
|
68
|
+
return @parameters[n] if @parameters && @parameters[n]
|
69
|
+
return nil unless @node.parameter(n)
|
70
|
+
@parameters = Array.new(@node.parameters.length) unless @parameters
|
71
|
+
@parameters[n] = @node.parameter(n).evaluate(@node, :params => true).to_s
|
72
|
+
@parameters[n].strip! if options[:strip]
|
73
|
+
@parameters[n]
|
27
74
|
end
|
28
75
|
|
29
|
-
#
|
76
|
+
# Returns a hash containing all evaluated macro attributes
|
77
|
+
# @param [Hash] options a hash of options
|
78
|
+
# @option options [Boolean] :strip whether the value is stripped or not
|
79
|
+
# @return [Hash] the macro attributes
|
80
|
+
# @since 0.3.0
|
81
|
+
def attributes(options={:strip => true})
|
82
|
+
return @attributes if @attributes
|
83
|
+
@attributes = {}
|
84
|
+
@node.attributes.each do |value|
|
85
|
+
@attributes[value[:name]] = value.evaluate(@node, :attrs => true)
|
86
|
+
@attributes[value[:name]].strip! if options[:strip]
|
87
|
+
end
|
88
|
+
@attributes
|
89
|
+
end
|
90
|
+
|
91
|
+
# Returns an array containing all evaluated macro parameters
|
92
|
+
# @param [Hash] options a hash of options
|
93
|
+
# @option options [Boolean] :strip whether the value is stripped or not
|
30
94
|
# @return [Array] the macro parameters
|
31
|
-
|
32
|
-
|
33
|
-
|
95
|
+
# @since 0.3.0
|
96
|
+
def parameters(options={:strip => true})
|
97
|
+
return @parameters if @parameters
|
98
|
+
@parameters = []
|
99
|
+
@node.parameters.each do |value|
|
100
|
+
@parameters << value.evaluate(@node, :params => true)
|
101
|
+
@parameters.last.strip! if options[:strip]
|
102
|
+
end
|
103
|
+
@parameters
|
104
|
+
end
|
105
|
+
|
106
|
+
alias params parameters
|
107
|
+
alias param parameter
|
108
|
+
alias attrs attributes
|
109
|
+
alias attr attribute
|
110
|
+
alias raw_param raw_parameter
|
111
|
+
alias raw_attr raw_attribute
|
112
|
+
|
113
|
+
# Equivalent to Glyph::Macro#parameter(0).
|
114
|
+
# @since 0.3.0
|
115
|
+
def value
|
116
|
+
parameter(0)
|
117
|
+
end
|
118
|
+
|
119
|
+
# Equivalent to Glyph::Macro#raw_parameter(0).
|
120
|
+
# @since 0.3.0
|
121
|
+
def raw_value
|
122
|
+
raw_parameter(0)
|
34
123
|
end
|
35
124
|
|
36
125
|
# Returns the "path" to the macro within the syntax tree.
|
37
126
|
# @return [String] the macro path
|
127
|
+
# @since 0.3.0
|
38
128
|
def path
|
39
129
|
macros = []
|
40
|
-
@node.ascend
|
41
|
-
|
130
|
+
@node.ascend do |n|
|
131
|
+
case
|
132
|
+
when n.is_a?(Glyph::MacroNode) then
|
133
|
+
if n[:name] == :"|xml|" then
|
134
|
+
name = "xml[#{n[:element]}]"
|
135
|
+
else
|
136
|
+
break if n[:name] == :include
|
137
|
+
name = n[:name].to_s
|
138
|
+
end
|
139
|
+
when n.is_a?(Glyph::ParameterNode) then
|
140
|
+
if n.parent.parameters.length == 1 then
|
141
|
+
name = nil
|
142
|
+
else
|
143
|
+
name = n[:name].to_s
|
144
|
+
end
|
145
|
+
when n.is_a?(Glyph::AttributeNode) then
|
146
|
+
name = "@#{n[:name]}"
|
147
|
+
else
|
148
|
+
name = nil
|
149
|
+
end
|
150
|
+
macros << name
|
151
|
+
end
|
152
|
+
macros.reverse.compact.join('/')
|
42
153
|
end
|
43
154
|
|
44
155
|
# Returns a todo message to include in the document in case of errors.
|
45
156
|
# @param [String] message the message to include in the document
|
46
157
|
# @return [String] the resulting todo message
|
158
|
+
# @since 0.2.0
|
47
159
|
def macro_todo(message)
|
48
160
|
draft = Glyph['document.draft']
|
49
161
|
Glyph['document.draft'] = true unless draft
|
@@ -56,57 +168,49 @@ module Glyph
|
|
56
168
|
# @param [String] msg the message to print
|
57
169
|
# @raise [Glyph::MacroError]
|
58
170
|
def macro_error(msg, klass=Glyph::MacroError)
|
59
|
-
|
60
|
-
|
61
|
-
src ||= "--"
|
62
|
-
message = "#{msg}\n -> source: #{src}\n -> path: #{path}"
|
63
|
-
@node[:document].errors << message
|
64
|
-
message += "\n -> value:\n#{"-"*54}\n#{@value}\n#{"-"*54}" if Glyph.debug?
|
65
|
-
raise klass, message
|
171
|
+
@node[:document].errors << msg if @node[:document]
|
172
|
+
raise klass.new(msg, self)
|
66
173
|
end
|
67
174
|
|
68
|
-
#
|
175
|
+
# Prints a macro earning
|
69
176
|
# @param [String] msg the message to print
|
70
|
-
# @
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
177
|
+
# @param [Exception] e the exception raised
|
178
|
+
# @since 0.2.0
|
179
|
+
def macro_warning(msg, e=nil)
|
180
|
+
if e.is_a?(Glyph::MacroError) then
|
181
|
+
e.display
|
182
|
+
else
|
183
|
+
message = "#{msg}\n source: #{@source}\n path: #{path}"
|
184
|
+
if Glyph.debug? then
|
185
|
+
message << %{\n#{"-"*54}\n#{@node.to_s.gsub(/\t/, ' ')}\n#{"-"*54}}
|
186
|
+
if e then
|
187
|
+
message << "\n"+"-"*20+"[ Backtrace: ]"+"-"*20
|
188
|
+
message << "\n"+e.backtrace.join("\n")
|
189
|
+
message << "\n"+"-"*54
|
190
|
+
end
|
191
|
+
end
|
192
|
+
Glyph.warning message
|
193
|
+
end
|
77
194
|
end
|
78
195
|
|
79
196
|
# Instantiates a Glyph::Interpreter and interprets a string
|
80
197
|
# @param [String] string the string to interpret
|
81
198
|
# @return [String] the interpreted output
|
82
|
-
# @raise [Glyph::MacroError] in case of mutual macro inclusion (snippet, include macros)
|
83
199
|
def interpret(string)
|
84
|
-
@node[:source] = "#@name[#@value]"
|
85
|
-
@node[:source_name] = "#{@name}[...]"
|
86
|
-
macro_error "Mutual inclusion", Glyph::MutualInclusionError if @node.find_parent {|n| n[:source] == @node[:source] }
|
87
200
|
if @node[:escape] then
|
88
201
|
result = string
|
89
202
|
else
|
90
|
-
|
91
|
-
|
203
|
+
context = {}
|
204
|
+
context[:source] = @updated_source || @node[:source]
|
205
|
+
context[:embedded] = true
|
206
|
+
context[:document] = @node[:document]
|
207
|
+
interpreter = Glyph::Interpreter.new string, context
|
208
|
+
subtree = interpreter.parse
|
209
|
+
@node << subtree
|
210
|
+
result = interpreter.document.output
|
92
211
|
end
|
93
212
|
result.gsub(/\\*([\[\]])/){"\\#$1"}
|
94
|
-
|
95
|
-
|
96
|
-
# Encodes all macros in a string so that it can be encoded
|
97
|
-
# (and interpreted) later on
|
98
|
-
# @param [String] string the string to encode
|
99
|
-
# @return [String] the encoded string
|
100
|
-
def encode(string)
|
101
|
-
string.gsub(/([\[\]\|])/) { "‡‡¤#{$1.bytes.to_a[0]}¤‡‡" }
|
102
|
-
end
|
103
|
-
|
104
|
-
# Decodes a previously encoded string
|
105
|
-
# so that it can be interpreted
|
106
|
-
# @param [String] string the string to decode
|
107
|
-
# @return [String] the decoded string
|
108
|
-
def decode(string)
|
109
|
-
string.gsub(/‡‡¤(91|93|124)¤‡‡/) { $1.to_i.chr }
|
213
|
+
result
|
110
214
|
end
|
111
215
|
|
112
216
|
# @see Glyph::Document#placeholder
|
@@ -135,12 +239,13 @@ module Glyph
|
|
135
239
|
end
|
136
240
|
|
137
241
|
# Executes a macro definition in the context of self
|
138
|
-
def
|
139
|
-
|
242
|
+
def expand
|
243
|
+
block = Glyph::MACROS[@name]
|
244
|
+
macro_error "Undefined macro '#@name'}" unless block
|
245
|
+
res = instance_exec(@node, &block).to_s
|
140
246
|
res.gsub!(/\\*([\[\]\|])/){"\\#$1"}
|
141
247
|
res
|
142
248
|
end
|
143
249
|
|
144
250
|
end
|
145
|
-
|
146
251
|
end
|