glyph 0.2.0 → 0.3.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.
- 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
|