glyph 0.1.0 → 0.2.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 +8 -0
- data/CHANGELOG.textile +260 -0
- data/LICENSE.textile +26 -0
- data/README.textile +49 -21
- data/Rakefile +17 -7
- data/VERSION +1 -1
- data/book/config.yml +11 -5
- data/book/document.glyph +24 -13
- data/book/lib/macros/reference.rb +41 -14
- data/book/output/html/glyph.html +2298 -687
- data/book/output/pdf/glyph.pdf +6218 -2698
- data/book/script/authors +1 -0
- data/book/script/changelog +1 -0
- data/book/script/compile.rb +8 -0
- data/book/script/license +1 -0
- data/book/script/prof +1 -0
- data/book/script/prof_results.htm +21079 -0
- data/book/script/readme +1 -0
- data/book/snippets.yml +3 -4
- data/book/text/acknowledgement.glyph +8 -0
- data/book/text/authoring.glyph +548 -0
- data/book/text/changelog.glyph +76 -0
- data/book/text/extending.glyph +224 -0
- data/book/text/{getting_started.textile → getting_started.glyph} +30 -24
- data/book/text/{introduction.textile → introduction.glyph} +22 -12
- data/book/text/license.glyph +21 -0
- data/book/text/{ref_commands.textile → ref_commands.glyph} +30 -8
- data/book/text/ref_config.glyph +108 -0
- data/book/text/ref_macros.glyph +378 -0
- data/book/text/troubleshooting.glyph +179 -0
- data/config.yml +16 -4
- data/glyph.gemspec +83 -22
- data/lib/glyph.rb +164 -31
- data/lib/glyph/commands.rb +98 -23
- data/lib/glyph/document.rb +13 -7
- data/lib/glyph/glyph_language.rb +9 -1
- data/lib/glyph/glyph_language.treetop +1 -1
- data/lib/glyph/interpreter.rb +19 -9
- data/lib/glyph/macro.rb +88 -11
- data/lib/glyph/macro_validators.rb +48 -0
- data/lib/glyph/node.rb +13 -1
- data/lib/glyph/system_extensions.rb +0 -28
- data/macros/common.rb +125 -31
- data/macros/filters.rb +19 -13
- data/macros/html/block.rb +119 -68
- data/macros/html/inline.rb +29 -3
- data/macros/html/structure.rb +40 -40
- data/spec/files/article.glyph +5 -0
- data/spec/lib/commands_spec.rb +98 -3
- data/spec/lib/document_spec.rb +15 -2
- data/spec/lib/glyph_spec.rb +39 -10
- data/spec/lib/interpreter_spec.rb +8 -2
- data/spec/lib/macro_spec.rb +54 -6
- data/spec/lib/macro_validators_spec.rb +33 -0
- data/spec/lib/node_spec.rb +11 -3
- data/spec/macros/filters_spec.rb +5 -5
- data/spec/macros/macros_spec.rb +185 -8
- data/spec/macros/textile_spec.rb +217 -0
- data/spec/spec_helper.rb +25 -15
- data/spec/tasks/generate_spec.rb +3 -3
- data/spec/tasks/load_spec.rb +11 -1
- data/spec/tasks/project_spec.rb +0 -3
- data/styles/coderay.css +121 -0
- data/styles/default.css +54 -20
- data/{book/styles/css3.css → styles/pagination.css} +35 -7
- data/styles/ultraviolet/active4d.css +114 -0
- data/styles/ultraviolet/all_hallows_eve.css +72 -0
- data/styles/ultraviolet/amy.css +147 -0
- data/styles/ultraviolet/blackboard.css +88 -0
- data/styles/ultraviolet/brilliance_black.css +605 -0
- data/styles/ultraviolet/brilliance_dull.css +599 -0
- data/styles/ultraviolet/cobalt.css +149 -0
- data/styles/ultraviolet/dawn.css +121 -0
- data/styles/ultraviolet/eiffel.css +121 -0
- data/styles/ultraviolet/espresso_libre.css +109 -0
- data/styles/ultraviolet/idle.css +62 -0
- data/styles/ultraviolet/iplastic.css +80 -0
- data/styles/ultraviolet/lazy.css +73 -0
- data/styles/ultraviolet/mac_classic.css +123 -0
- data/styles/ultraviolet/magicwb_amiga.css +104 -0
- data/styles/ultraviolet/pastels_on_dark.css +188 -0
- data/styles/ultraviolet/slush_poppies.css +85 -0
- data/styles/ultraviolet/spacecadet.css +51 -0
- data/styles/ultraviolet/sunburst.css +180 -0
- data/styles/ultraviolet/twilight.css +137 -0
- data/styles/ultraviolet/zenburnesque.css +91 -0
- data/tasks/generate.rake +45 -26
- data/tasks/load.rake +21 -18
- data/tasks/project.rake +3 -1
- metadata +210 -41
- data/book/styles/default.css +0 -190
- data/book/text/authoring.textile +0 -351
- data/book/text/extending.textile +0 -148
- data/book/text/ref_config.textile +0 -0
- data/book/text/ref_macros.textile +0 -256
- data/book/text/troubleshooting.textile +0 -118
- data/styles/css3.css +0 -220
data/lib/glyph/commands.rb
CHANGED
@@ -21,24 +21,92 @@ command :add do |c|
|
|
21
21
|
end
|
22
22
|
|
23
23
|
GLI.desc 'Compile the project'
|
24
|
-
arg_name "[
|
24
|
+
arg_name "[source_file]"
|
25
|
+
arg_name "[destination_file]"
|
25
26
|
command :compile do |c|
|
26
27
|
c.desc "Specify a glyph file to compile (default: document.glyph)"
|
27
28
|
c.flag [:s, :source]
|
28
29
|
c.desc "Specify the format of the output file (default: html)"
|
29
30
|
c.flag [:f, :format]
|
31
|
+
c.desc "Auto-regenerate output on file changes"
|
32
|
+
c.switch :auto
|
30
33
|
c.action do |global_options, options, args|
|
31
|
-
|
34
|
+
raise ArgumentError, "Too many arguments" if args.length > 2
|
35
|
+
Glyph.lite_mode = true unless args.blank?
|
36
|
+
Glyph.run! 'load:config'
|
37
|
+
original_config = Glyph::CONFIG.dup
|
32
38
|
output_targets = Glyph::CONFIG.get('document.output_targets')
|
33
39
|
target = nil
|
34
|
-
Glyph
|
35
|
-
target =
|
40
|
+
Glyph['document.output'] = options[:f] if options[:f]
|
41
|
+
target = Glyph['document.output']
|
36
42
|
target = nil if target.blank?
|
37
|
-
target ||=
|
38
|
-
Glyph
|
43
|
+
target ||= Glyph['filters.target']
|
44
|
+
Glyph['document.source'] = options[:s] if options[:s]
|
39
45
|
raise ArgumentError, "Output target not specified" unless target
|
40
46
|
raise ArgumentError, "Unknown output target '#{target}'" unless output_targets.include? target.to_sym
|
41
|
-
|
47
|
+
|
48
|
+
# Lite mode
|
49
|
+
if Glyph.lite? then
|
50
|
+
source_file = Pathname.new args[0]
|
51
|
+
filename = source_file.basename(source_file.extname).to_s
|
52
|
+
destination_file = Pathname.new(args[1]) rescue nil
|
53
|
+
src_extension = Regexp.escape(source_file.extname)
|
54
|
+
dst_extension = ".#{Glyph['document.output']}"
|
55
|
+
destination_file ||= Pathname.new(source_file.to_s.gsub(/#{src_extension}$/, dst_extension))
|
56
|
+
raise ArgumentError, "Source file '#{source_file}' does not exist" unless source_file.exist?
|
57
|
+
raise ArgumentError, "Source and destination file are the same" if source_file.to_s == destination_file.to_s
|
58
|
+
Glyph['document.filename'] = filename
|
59
|
+
Glyph['document.source'] = source_file.to_s
|
60
|
+
Glyph['document.output_dir'] = destination_file.parent.to_s # System use only
|
61
|
+
Glyph['document.output_file'] = destination_file.basename.to_s # System use only
|
62
|
+
end
|
63
|
+
begin
|
64
|
+
Glyph.run "generate:#{target}"
|
65
|
+
rescue Exception => e
|
66
|
+
message = e.message
|
67
|
+
if Glyph.debug? then
|
68
|
+
message << "\n"+"-"*20+"[ Backtrace: ]"+"-"*20
|
69
|
+
message << "\n"+e.backtrace.join("\n")
|
70
|
+
message << "\n"+"-"*54
|
71
|
+
end
|
72
|
+
raise RuntimeError, message if Glyph.library?
|
73
|
+
Glyph.error message
|
74
|
+
end
|
75
|
+
|
76
|
+
# Auto-regeneration
|
77
|
+
if options[:auto] && !Glyph.lite? then
|
78
|
+
Glyph.lite_mode = false
|
79
|
+
begin
|
80
|
+
require 'directory_watcher'
|
81
|
+
rescue LoadError
|
82
|
+
raise RuntimeError, "DirectoryWatcher is not available. Install it with: gem install directory_watcher"
|
83
|
+
end
|
84
|
+
Glyph.info 'Auto-regeneration enabled'
|
85
|
+
Glyph.info 'Use ^C to interrupt'
|
86
|
+
glob = ['*.glyph', 'config.yml', 'images/**/*', 'lib/**/*', 'snippets.yml', 'styles/**/*', 'text/**/*']
|
87
|
+
dw = DirectoryWatcher.new(Glyph::PROJECT, :glob => glob, :interval => 1, :pre_load => true)
|
88
|
+
dw.add_observer do |*args|
|
89
|
+
puts "="*50
|
90
|
+
Glyph.info "Regeneration started: #{args.size} files changed"
|
91
|
+
Glyph.reset
|
92
|
+
begin
|
93
|
+
Glyph.run! "generate:#{target}"
|
94
|
+
rescue Exception => e
|
95
|
+
Glyph.error e.message
|
96
|
+
if Glyph.debug? then
|
97
|
+
puts "-"*20+"[ Backtrace: ]"+"-"*20
|
98
|
+
puts e.backtrace
|
99
|
+
pits "-"*54
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
dw.start
|
104
|
+
begin
|
105
|
+
sleep
|
106
|
+
rescue Interrupt
|
107
|
+
end
|
108
|
+
dw.stop
|
109
|
+
end
|
42
110
|
end
|
43
111
|
end
|
44
112
|
|
@@ -46,13 +114,13 @@ GLI.desc 'Display all project TODO items'
|
|
46
114
|
command :todo do |c|
|
47
115
|
c.action do |global_options, options, args|
|
48
116
|
Glyph.run "generate:document"
|
49
|
-
unless Glyph
|
50
|
-
info "*** TODOs: ***"
|
51
|
-
Glyph
|
52
|
-
info t
|
117
|
+
unless Glyph.document.todos.blank?
|
118
|
+
Glyph.info "*** TODOs: ***"
|
119
|
+
Glyph.document.todos.each do |t|
|
120
|
+
Glyph.info t
|
53
121
|
end
|
54
122
|
else
|
55
|
-
info "Nothing left to do."
|
123
|
+
Glyph.info "Nothing left to do."
|
56
124
|
end
|
57
125
|
end
|
58
126
|
end
|
@@ -65,20 +133,27 @@ command :config do |c|
|
|
65
133
|
c.action do |global_options,options,args|
|
66
134
|
Glyph.run 'load:config'
|
67
135
|
if options[:g] then
|
68
|
-
|
136
|
+
config = Glyph::GLOBAL_CONFIG
|
69
137
|
else
|
70
|
-
|
138
|
+
config = Glyph::PROJECT_CONFIG
|
71
139
|
end
|
72
140
|
case args.length
|
73
141
|
when 0 then
|
74
142
|
raise ArgumentError, "Too few arguments."
|
75
143
|
when 1 then # read current config
|
76
|
-
setting =
|
144
|
+
setting = Glyph[args[0]]
|
77
145
|
raise RuntimeError, "Unknown setting '#{args[0]}'" if setting.blank?
|
78
|
-
info
|
146
|
+
Glyph.info setting
|
79
147
|
when 2 then
|
80
|
-
|
81
|
-
Glyph.
|
148
|
+
# Remove all overrides
|
149
|
+
Glyph.config_reset
|
150
|
+
# Reload current project config
|
151
|
+
config.read
|
152
|
+
config.set args[0], args[1]
|
153
|
+
# Write changes to file
|
154
|
+
config.write
|
155
|
+
# Refresh configuration
|
156
|
+
Glyph.config_refresh
|
82
157
|
else
|
83
158
|
raise ArgumentError, "Too many arguments."
|
84
159
|
end
|
@@ -90,7 +165,7 @@ pre do |global,command,options,args|
|
|
90
165
|
# Return true to proceed; false to abourt and not call the
|
91
166
|
# chosen command
|
92
167
|
if global[:d] then
|
93
|
-
Glyph
|
168
|
+
Glyph.debug_mode = true
|
94
169
|
end
|
95
170
|
if !command || command.name == :help then
|
96
171
|
puts "====================================="
|
@@ -105,17 +180,17 @@ post do |global,command,options,args|
|
|
105
180
|
end
|
106
181
|
|
107
182
|
on_error do |exception|
|
108
|
-
if exception.is_a? MacroError then
|
109
|
-
|
110
|
-
puts exception.message
|
183
|
+
if exception.is_a? Glyph::MacroError then
|
184
|
+
Glyph.warning exception.message
|
111
185
|
false
|
112
186
|
else
|
113
|
-
if Glyph.
|
187
|
+
if Glyph.debug? then
|
114
188
|
puts "Exception: #{exception.message}"
|
115
189
|
puts "Backtrace:"
|
116
190
|
exception.backtrace.each do |b|
|
117
191
|
puts b
|
118
192
|
end
|
193
|
+
Glyph.debug_mode = false
|
119
194
|
end
|
120
195
|
true
|
121
196
|
end
|
data/lib/glyph/document.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
1
3
|
module Glyph
|
2
4
|
|
3
5
|
# The Glyph::Document class stores information about a document or a chunk of text
|
@@ -16,19 +18,20 @@ module Glyph
|
|
16
18
|
['\\|', '|']
|
17
19
|
]
|
18
20
|
|
19
|
-
attr_reader :bookmarks, :placeholders, :headers, :context
|
21
|
+
attr_reader :bookmarks, :placeholders, :headers, :context, :errors, :todos
|
20
22
|
|
21
23
|
# Creates a new document
|
22
24
|
# @param [GlyphSyntaxNode] tree the syntax tree to be evaluate
|
23
25
|
# @param [Glyph::Node] context the context associated with the tree
|
24
26
|
# @raise [RuntimeError] unless tree responds to :evaluate
|
25
27
|
def initialize(tree, context)
|
26
|
-
raise RuntimeError, "Document contains syntax errors." unless tree.respond_to? :evaluate
|
27
28
|
@tree = tree
|
28
29
|
@context = context
|
29
30
|
@bookmarks = {}
|
30
31
|
@placeholders = {}
|
31
32
|
@headers = []
|
33
|
+
@errors = []
|
34
|
+
@todos = []
|
32
35
|
@state = :new
|
33
36
|
end
|
34
37
|
|
@@ -40,11 +43,12 @@ module Glyph
|
|
40
43
|
@tree.data
|
41
44
|
end
|
42
45
|
|
43
|
-
# Copies bookmarks, headers and placeholders from another Glyph::Document
|
46
|
+
# Copies bookmarks, headers, todos and placeholders from another Glyph::Document
|
44
47
|
# @param [Glyph::Document] document a valid Glyph::Document
|
45
48
|
def inherit_from(document)
|
46
49
|
@bookmarks = document.bookmarks
|
47
50
|
@headers = document.headers
|
51
|
+
@todos = document.todos
|
48
52
|
@placeholders = document.placeholders
|
49
53
|
end
|
50
54
|
|
@@ -101,18 +105,20 @@ module Glyph
|
|
101
105
|
|
102
106
|
# Finalizes the document by evaluating its @placeholders
|
103
107
|
# @return [:finalized]
|
104
|
-
# @raise [RuntimeError]
|
105
|
-
# if it is already finalized
|
108
|
+
# @raise [RuntimeError] if the document the document has not been analyzed,
|
109
|
+
# if it is already finalized or if errors occurred during analysis
|
106
110
|
def finalize
|
107
111
|
raise RuntimeError, "Document has not been analyzed" unless analyzed?
|
108
112
|
raise RuntimeError, "Document has already been finalized" if finalized?
|
109
|
-
return (@state = :finalized) if @context[:
|
113
|
+
return (@state = :finalized) if @context[:embedded]
|
114
|
+
raise RuntimeError, "Document cannot be finalized due to previous errors" unless @context[:document].errors.blank?
|
115
|
+
# Substitute placeholders
|
110
116
|
ESCAPES.each{|e| @output.gsub! e[0], e[1]}
|
111
117
|
@placeholders.each_pair do |key, value|
|
112
118
|
begin
|
113
119
|
@output.gsub! key.to_s, value.call(self).to_s
|
114
120
|
rescue Exception => e
|
115
|
-
warning e.message
|
121
|
+
Glyph.warning e.message
|
116
122
|
end
|
117
123
|
end
|
118
124
|
@state = :finalized
|
data/lib/glyph/glyph_language.rb
CHANGED
@@ -49,6 +49,7 @@ module GlyphLanguage
|
|
49
49
|
r0
|
50
50
|
end
|
51
51
|
|
52
|
+
# @private
|
52
53
|
module EscapingMacro0
|
53
54
|
def macro_name
|
54
55
|
elements[0]
|
@@ -96,7 +97,7 @@ module GlyphLanguage
|
|
96
97
|
end
|
97
98
|
end
|
98
99
|
if s0.last
|
99
|
-
r0 = instantiate_node(
|
100
|
+
r0 = instantiate_node(EscapingMacroNode,input, i0...index, s0)
|
100
101
|
r0.extend(EscapingMacro0)
|
101
102
|
else
|
102
103
|
@index = i0
|
@@ -108,6 +109,7 @@ module GlyphLanguage
|
|
108
109
|
r0
|
109
110
|
end
|
110
111
|
|
112
|
+
# @private
|
111
113
|
module Macro0
|
112
114
|
def macro_name
|
113
115
|
elements[0]
|
@@ -167,9 +169,11 @@ module GlyphLanguage
|
|
167
169
|
r0
|
168
170
|
end
|
169
171
|
|
172
|
+
# @private
|
170
173
|
module EscapedText0
|
171
174
|
end
|
172
175
|
|
176
|
+
# @private
|
173
177
|
module EscapedText1
|
174
178
|
def macro_name
|
175
179
|
elements[0]
|
@@ -177,6 +181,7 @@ module GlyphLanguage
|
|
177
181
|
|
178
182
|
end
|
179
183
|
|
184
|
+
# @private
|
180
185
|
module EscapedText2
|
181
186
|
end
|
182
187
|
|
@@ -345,9 +350,11 @@ module GlyphLanguage
|
|
345
350
|
r0
|
346
351
|
end
|
347
352
|
|
353
|
+
# @private
|
348
354
|
module Text0
|
349
355
|
end
|
350
356
|
|
357
|
+
# @private
|
351
358
|
module Text1
|
352
359
|
def macro_name
|
353
360
|
elements[0]
|
@@ -355,6 +362,7 @@ module GlyphLanguage
|
|
355
362
|
|
356
363
|
end
|
357
364
|
|
365
|
+
# @private
|
358
366
|
module Text2
|
359
367
|
end
|
360
368
|
|
data/lib/glyph/interpreter.rb
CHANGED
@@ -6,27 +6,29 @@ class GlyphSyntaxNode < Treetop::Runtime::SyntaxNode
|
|
6
6
|
def evaluate(context, current=nil)
|
7
7
|
current ||= context.to_node
|
8
8
|
@data ||= current.to_node
|
9
|
-
|
10
|
-
value
|
9
|
+
elements.map { |e| e.evaluate(context, current) if e.respond_to? :evaluate }.join
|
11
10
|
end
|
12
11
|
|
13
|
-
end
|
12
|
+
end
|
14
13
|
|
15
14
|
# @private
|
16
15
|
class MacroNode < GlyphSyntaxNode
|
17
16
|
|
18
|
-
def evaluate(context, current
|
17
|
+
def evaluate(context, current)
|
19
18
|
name = macro_name.text_value.to_sym
|
20
|
-
raise
|
19
|
+
raise Glyph::SyntaxError, "Undefined macro '#{name}'\n -> source: #{current[:source]}" unless Glyph::MACROS.include? name
|
21
20
|
@data = {:macro => name, :source => context[:source], :document => context[:document]}.to_node
|
21
|
+
@data[:escape] = true if is_a? EscapingMacroNode
|
22
22
|
current << @data
|
23
|
-
value = super(context, @data).strip
|
24
|
-
@data[:value] = value
|
23
|
+
@data[:value] = super(context, @data).strip
|
25
24
|
Glyph::Macro.new(@data).execute
|
26
25
|
end
|
27
26
|
|
28
27
|
end
|
29
28
|
|
29
|
+
# @private
|
30
|
+
class EscapingMacroNode < MacroNode; end
|
31
|
+
|
30
32
|
# @private
|
31
33
|
class TextNode < GlyphSyntaxNode
|
32
34
|
|
@@ -45,14 +47,22 @@ module Glyph
|
|
45
47
|
# * Analyzes and finalizes the document
|
46
48
|
class Interpreter
|
47
49
|
|
50
|
+
PARSER = GlyphLanguageParser.new
|
51
|
+
|
48
52
|
# Creates a new Glyph::Interpreter object.
|
49
53
|
# @param [String] text the string to interpret
|
50
54
|
# @param [Hash] context the context to pass along when evaluating macros
|
51
55
|
def initialize(text, context=nil)
|
52
56
|
context ||= {:source => '--'}
|
53
|
-
@
|
54
|
-
@raw = @parser.parse text
|
57
|
+
@raw = PARSER.parse text
|
55
58
|
@context = context
|
59
|
+
tf = PARSER.terminal_failures
|
60
|
+
if !@raw.respond_to?(:evaluate) then
|
61
|
+
reason = "Incorrect macro syntax"
|
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
|
56
66
|
@document = Glyph::Document.new @raw, @context
|
57
67
|
@document.inherit_from @context[:document] if @context[:document]
|
58
68
|
end
|
data/lib/glyph/macro.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
1
3
|
module Glyph
|
2
4
|
|
3
5
|
# A Macro object is instantiated by a Glyph::Interpreter whenever a macro is found in the parsed text.
|
@@ -5,6 +7,8 @@ module Glyph
|
|
5
7
|
# useful methods to be used in macro definitions.
|
6
8
|
class Macro
|
7
9
|
|
10
|
+
include Validators
|
11
|
+
|
8
12
|
# Creates a new macro instance from a Node
|
9
13
|
# @param [Node] node a node populated with macro data
|
10
14
|
def initialize(node)
|
@@ -12,26 +16,97 @@ module Glyph
|
|
12
16
|
@name = @node[:macro]
|
13
17
|
@value = @node[:value]
|
14
18
|
@source = @node[:source]
|
15
|
-
|
16
|
-
|
19
|
+
@escaped_pipe = '‡‡‡‡‡ESCAPED¤PIPE‡‡‡‡‡'
|
20
|
+
end
|
21
|
+
|
22
|
+
# Parses the macro parameters (stripping values)
|
23
|
+
# @return [Array] the macro parameters
|
24
|
+
def params
|
25
|
+
return @params if @params
|
26
|
+
@params = @value.gsub(/\\\|/, @escaped_pipe).split('|').map{|p| p.strip.gsub @escaped_pipe, "\\|"}
|
27
|
+
end
|
28
|
+
|
29
|
+
# Parses the macro parameters (without stripping values)
|
30
|
+
# @return [Array] the macro parameters
|
31
|
+
def raw_params
|
32
|
+
return @raw_params if @raw_params
|
33
|
+
@params = @value.gsub(/\\\|/, @escaped_pipe).split('|').map{|p| p.gsub @escaped_pipe, "\\|"}
|
34
|
+
end
|
35
|
+
|
36
|
+
# Returns the "path" to the macro within the syntax tree.
|
37
|
+
# @return [String] the macro path
|
38
|
+
def path
|
39
|
+
macros = []
|
40
|
+
@node.ascend {|n| macros << n[:macro].to_s if n[:macro] }
|
41
|
+
macros.reverse.join('/')
|
42
|
+
end
|
43
|
+
|
44
|
+
# Returns a todo message to include in the document in case of errors.
|
45
|
+
# @param [String] message the message to include in the document
|
46
|
+
# @return [String] the resulting todo message
|
47
|
+
def macro_todo(message)
|
48
|
+
draft = Glyph['document.draft']
|
49
|
+
Glyph['document.draft'] = true unless draft
|
50
|
+
res = interpret "![#{message}]"
|
51
|
+
Glyph['document.draft'] = false unless draft
|
52
|
+
res
|
53
|
+
end
|
54
|
+
|
55
|
+
# Raises a macro error (preventing document post-processing)
|
56
|
+
# @param [String] msg the message to print
|
57
|
+
# @raise [Glyph::MacroError]
|
58
|
+
def macro_error(msg, klass=Glyph::MacroError)
|
59
|
+
src = @node[:source_name]
|
60
|
+
src ||= @node[:source]
|
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
|
17
66
|
end
|
18
67
|
|
19
68
|
# Raises a macro error
|
20
69
|
# @param [String] msg the message to print
|
21
|
-
# @raise [MacroError]
|
22
|
-
def
|
23
|
-
|
70
|
+
# @raise [Glyph::MacroError]
|
71
|
+
def macro_warning(message)
|
72
|
+
src = @node[:source_name]
|
73
|
+
src ||= @node[:source]
|
74
|
+
src ||= "--"
|
75
|
+
Glyph.warning "#{message}\n -> source: #{src}\n -> path: #{path}"
|
76
|
+
message += %{\n -> value:\n#{"-"*54}\n#{@value}\n#{"-"*54}} if Glyph.debug?
|
24
77
|
end
|
25
78
|
|
26
79
|
# Instantiates a Glyph::Interpreter and interprets a string
|
27
80
|
# @param [String] string the string to interpret
|
28
81
|
# @return [String] the interpreted output
|
29
|
-
# @raise [MacroError] in case of mutual macro inclusion (snippet, include macros)
|
82
|
+
# @raise [Glyph::MacroError] in case of mutual macro inclusion (snippet, include macros)
|
30
83
|
def interpret(string)
|
31
|
-
@node[:source] = "
|
32
|
-
@node[:
|
33
|
-
macro_error "Mutual inclusion" if @node.find_parent {|n| n[:source] == @node[:source] }
|
34
|
-
|
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
|
+
if @node[:escape] then
|
88
|
+
result = string
|
89
|
+
else
|
90
|
+
@node[:embedded] = true
|
91
|
+
result = Glyph::Interpreter.new(string, @node).document.output
|
92
|
+
end
|
93
|
+
result.gsub(/\\*([\[\]])/){"\\#$1"}
|
94
|
+
end
|
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 }
|
35
110
|
end
|
36
111
|
|
37
112
|
# @see Glyph::Document#placeholder
|
@@ -61,7 +136,9 @@ module Glyph
|
|
61
136
|
|
62
137
|
# Executes a macro definition in the context of self
|
63
138
|
def execute
|
64
|
-
instance_exec(@node, &Glyph::MACROS[@name]).to_s
|
139
|
+
res = instance_exec(@node, &Glyph::MACROS[@name]).to_s
|
140
|
+
res.gsub!(/\\*([\[\]\|])/){"\\#$1"}
|
141
|
+
res
|
65
142
|
end
|
66
143
|
|
67
144
|
end
|