lib/glyph/macro.rb in glyph-0.1.0 vs lib/glyph/macro.rb in glyph-0.2.0
- old
+ new
@@ -1,41 +1,116 @@
+# encoding: utf-8
+
module Glyph
# A Macro object is instantiated by a Glyph::Interpreter whenever a macro is found in the parsed text.
# The Macro class contains shortcut methods to access the current node and document, as well as other
# useful methods to be used in macro definitions.
class Macro
+ include Validators
+
# Creates a new macro instance from a Node
# @param [Node] node a node populated with macro data
def initialize(node)
@node = node
@name = @node[:macro]
@value = @node[:value]
@source = @node[:source]
- esc = '‡‡‡‡‡ESCAPED¤PIPE‡‡‡‡‡'
- @params = @value.gsub(/\\\|/, esc).split('|').map{|p| p.strip.gsub esc, '|'}
+ @escaped_pipe = '‡‡‡‡‡ESCAPED¤PIPE‡‡‡‡‡'
end
+ # Parses the macro parameters (stripping values)
+ # @return [Array] the macro parameters
+ def params
+ return @params if @params
+ @params = @value.gsub(/\\\|/, @escaped_pipe).split('|').map{|p| p.strip.gsub @escaped_pipe, "\\|"}
+ end
+
+ # Parses the macro parameters (without stripping values)
+ # @return [Array] the macro parameters
+ def raw_params
+ return @raw_params if @raw_params
+ @params = @value.gsub(/\\\|/, @escaped_pipe).split('|').map{|p| p.gsub @escaped_pipe, "\\|"}
+ end
+
+ # Returns the "path" to the macro within the syntax tree.
+ # @return [String] the macro path
+ def path
+ macros = []
+ @node.ascend {|n| macros << n[:macro].to_s if n[:macro] }
+ macros.reverse.join('/')
+ end
+
+ # Returns a todo message to include in the document in case of errors.
+ # @param [String] message the message to include in the document
+ # @return [String] the resulting todo message
+ def macro_todo(message)
+ draft = Glyph['document.draft']
+ Glyph['document.draft'] = true unless draft
+ res = interpret "![#{message}]"
+ Glyph['document.draft'] = false unless draft
+ res
+ end
+
+ # Raises a macro error (preventing document post-processing)
+ # @param [String] msg the message to print
+ # @raise [Glyph::MacroError]
+ def macro_error(msg, klass=Glyph::MacroError)
+ src = @node[:source_name]
+ src ||= @node[:source]
+ src ||= "--"
+ message = "#{msg}\n -> source: #{src}\n -> path: #{path}"
+ @node[:document].errors << message
+ message += "\n -> value:\n#{"-"*54}\n#{@value}\n#{"-"*54}" if Glyph.debug?
+ raise klass, message
+ end
+
# Raises a macro error
# @param [String] msg the message to print
- # @raise [MacroError]
- def macro_error(msg)
- raise MacroError.new @node, msg
+ # @raise [Glyph::MacroError]
+ def macro_warning(message)
+ src = @node[:source_name]
+ src ||= @node[:source]
+ src ||= "--"
+ Glyph.warning "#{message}\n -> source: #{src}\n -> path: #{path}"
+ message += %{\n -> value:\n#{"-"*54}\n#{@value}\n#{"-"*54}} if Glyph.debug?
end
# Instantiates a Glyph::Interpreter and interprets a string
# @param [String] string the string to interpret
# @return [String] the interpreted output
- # @raise [MacroError] in case of mutual macro inclusion (snippet, include macros)
+ # @raise [Glyph::MacroError] in case of mutual macro inclusion (snippet, include macros)
def interpret(string)
- @node[:source] = "#{@name}: #{@value}"
- @node[:analyze_only] = true
- macro_error "Mutual inclusion" if @node.find_parent {|n| n[:source] == @node[:source] }
- Glyph::Interpreter.new(string, @node).document.output
+ @node[:source] = "#@name[#@value]"
+ @node[:source_name] = "#{@name}[...]"
+ macro_error "Mutual inclusion", Glyph::MutualInclusionError if @node.find_parent {|n| n[:source] == @node[:source] }
+ if @node[:escape] then
+ result = string
+ else
+ @node[:embedded] = true
+ result = Glyph::Interpreter.new(string, @node).document.output
+ end
+ result.gsub(/\\*([\[\]])/){"\\#$1"}
end
+ # Encodes all macros in a string so that it can be encoded
+ # (and interpreted) later on
+ # @param [String] string the string to encode
+ # @return [String] the encoded string
+ def encode(string)
+ string.gsub(/([\[\]\|])/) { "‡‡¤#{$1.bytes.to_a[0]}¤‡‡" }
+ end
+
+ # Decodes a previously encoded string
+ # so that it can be interpreted
+ # @param [String] string the string to decode
+ # @return [String] the decoded string
+ def decode(string)
+ string.gsub(/‡‡¤(91|93|124)¤‡‡/) { $1.to_i.chr }
+ end
+
# @see Glyph::Document#placeholder
def placeholder(&block)
@node[:document].placeholder &block
end
@@ -59,10 +134,12 @@
@node[:document].header hash
end
# Executes a macro definition in the context of self
def execute
- instance_exec(@node, &Glyph::MACROS[@name]).to_s
+ res = instance_exec(@node, &Glyph::MACROS[@name]).to_s
+ res.gsub!(/\\*([\[\]\|])/){"\\#$1"}
+ res
end
end
end