class Glyph::Macro
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.
Attributes
Public Class Methods
Creates a new macro instance from a Node
@param [Node] node a node populated with macro data
# File lib/glyph/macro.rb, line 17 def initialize(node) @data = {} @node = node @name = @node[:name] @updated_source = nil @source_name = @node[:source][:name] || nil rescue "--" @source_topic = @node[:source][:topic] || nil rescue "--" @source_file = @node[:source][:file] rescue nil end
Public Instance Methods
Performs parameter/attribute substitution and interprets text @since 0.5.0 @param [String] text the text to interpret @return [String] the interpreted output
# File lib/glyph/macro.rb, line 284 def apply(text) body = text.dup # Parameters body.gsub!(/\{\{(\d+)\}\}/) do raw_param($1.to_i).to_s.strip end # Attributes body.gsub!(/\{\{([^\[\]\|\\\s]+)\}\}/) do raw_attr($1.to_sym).to_s.strip end interpret body end
Returns an evaluated macro attribute by name @param [String, Symbol] name the name of the attribute @param [Hash] options a hash of options @option options [Boolean] :strip whether the value is stripped or not @return [String, nil] the value of the attribute @since 0.3.0
# File lib/glyph/macro.rb, line 60 def attribute(name, options={:strip => true, :null_if_blank => true}) return @attributes[name.to_sym] if @attributes && @attributes[name.to_sym] return nil unless @node.attribute(name) @attributes = {} unless @attributes @attributes[name] = @node.attribute(name).evaluate(@node, :attrs => true).to_s @attributes[name].strip! if options[:strip] @attributes[name] = nil if @attributes[name].blank? && options[:null_if_blank] @attributes[name] end
Returns a hash containing all evaluated macro attributes @param [Hash] options a hash of options @option options [Boolean] :strip whether the value is stripped or not @return [Hash] the macro attributes @since 0.3.0
# File lib/glyph/macro.rb, line 91 def attributes(options={:strip => true, :null_if_blank => true}) return @attributes if @attributes @attributes = {} @node.attributes.each do |value| @attributes[value[:name]] = value.evaluate(@node, :attrs => true) @attributes[value[:name]].strip! if options[:strip] @attributes[value[:name]] = nil if @attributes[value[:name]].blank? && options[:null_if_blank] end @attributes end
# File lib/glyph/macro.rb, line 221 def bookmark(hash) @node[:document].bookmark hash end
@see Glyph::Document#bookmark?
# File lib/glyph/macro.rb, line 226 def bookmark?(ident) @node[:document].bookmark? ident end
Stores a block of code to be “dispatched” via macro composition @since 0.5.0 @example
# Macro definition (Ruby) macro :greet do dispatch do |node| "#{node[:name]}, #{node.param 0}!" end end # macro usage (Glyph) greet/Hello[World] --[Outputs: Hello, World!] greet/GoodBye[John] --[Outputs: Goodbye, John!]
# File lib/glyph/macro.rb, line 275 def dispatch(&block) @node[:dispatch] = block value end
Executes a macro definition in the context of self
# File lib/glyph/macro.rb, line 319 def expand block = Glyph::MACROS[@name] macro_error "Undefined macro '#@name'" unless block instance_exec(@node, &block).to_s.gsub(/\\?([\[\]\|])/){"\\#$1"} end
# File lib/glyph/macro.rb, line 236 def header(hash) @node[:document].header hash end
# File lib/glyph/macro.rb, line 231 def header?(ident) @node[:document].header? ident end
Parses text and injects the syntax tree into the current node @since 0.5.0 @param [String] text the text to parse @return [Glyph::Interpreter] the interpreter instance used to parse text
# File lib/glyph/macro.rb, line 301 def inject(text) context = create_context interpreter = Glyph::Interpreter.new text, context subtree = interpreter.parse subtree[:source] = context[:source] @node << subtree interpreter end
Instantiates a Glyph::Interpreter
and interprets a string @param [String] string the string to interpret @return [String] the interpreted output
# File lib/glyph/macro.rb, line 211 def interpret(string) @node[:escape] ? string : inject(string).document.output end
Raises a macro error (preventing document post-processing) @param [String] msg the message to print @raise [Glyph::MacroError]
# File lib/glyph/macro.rb, line 182 def macro_error(msg, klass=Glyph::MacroError) @node[:document].errors << msg if @node[:document] raise klass.new(msg, self) 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 @since 0.2.0
# File lib/glyph/macro.rb, line 171 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
Prints a macro earning @param [String] msg the message to print @param [Exception] e the exception raised @since 0.2.0
# File lib/glyph/macro.rb, line 191 def macro_warning(msg, e=nil) if e.is_a?(Glyph::MacroError) then e.display else message = "#{msg}\n source: #{@source_name}\n path: #{path}" if Glyph.debug? then message << %{\n#{"-"*54}\n#{@node.to_s.gsub(/\t/, ' ')}\n#{"-"*54}} if e then message << "\n"+"-"*20+"[ Backtrace: ]"+"-"*20 message << "\n"+e.backtrace.join("\n") message << "\n"+"-"*54 end end Glyph.warning message end end
Returns an evaluated macro parameter by index @param [Fixnum] n the index of the parameter @param [Hash] options a hash of options @option options [Boolean] :strip whether the value is stripped or not @return [String, nil] the value of the parameter @since 0.3.0
# File lib/glyph/macro.rb, line 76 def parameter(n, options={:strip => true, :null_if_blank => true}) return @parameters[n] if @parameters && @parameters[n] return nil unless @node.parameter(n) @parameters = Array.new(@node.parameters.length) unless @parameters @parameters[n] = @node.parameter(n).evaluate(@node, :params => true).to_s @parameters[n].strip! if options[:strip] @parameters[n] = nil if @parameters[n].blank? && options[:null_if_blank] @parameters[n] end
Returns an array containing all evaluated macro parameters @param [Hash] options a hash of options @option options [Boolean] :strip whether the value is stripped or not @return [Array] the macro parameters @since 0.3.0
# File lib/glyph/macro.rb, line 107 def parameters(options={:strip => true, :null_if_blank => true}) return @parameters if @parameters @parameters = [] @node.parameters.each do |value| @parameters << value.evaluate(@node, :params => true) @parameters[@parameters.length-1].strip! if options[:strip] @parameters[@parameters.length-1] = nil if @parameters.last.blank? && options[:null_if_blank] end @parameters end
Parses text @since 0.5.0 @param [String] text the text to parse @return [Glyph::Node] the syntax tree generated by parsing
# File lib/glyph/macro.rb, line 314 def parse(text) Glyph::Interpreter.new(text, create_context).parse end
Returns the “path” to the macro within the syntax tree. @return [String] the macro path @since 0.3.0
# File lib/glyph/macro.rb, line 140 def path macros = [] @node.ascend do |n| case when n.is_a?(Glyph::MacroNode) then if n[:name] == :"|xml|" then name = "xml[#{n[:element]}]" else break if n[:name] == :include name = n[:name].to_s end when n.is_a?(Glyph::ParameterNode) then if n.parent.parameters.length == 1 then name = nil else name = n[:name].to_s end when n.is_a?(Glyph::AttributeNode) then name = "@#{n[:name]}" else name = nil end macros << name end macros.reverse.compact.join('/') end
@see Glyph::Document#placeholder
# File lib/glyph/macro.rb, line 216 def placeholder(&block) @node[:document].placeholder &block end
Returns a Glyph
code representation of the specified attribute @param [String, Symbol] name the name of the attribute @return [String, nil] the string representation of the attribute @since 0.3.0
# File lib/glyph/macro.rb, line 50 def raw_attribute(name) @node.attribute(name).contents.to_s rescue nil end
Returns a Glyph
code representation of the specified parameter @param [Fixnum] n the index of the parameter @return [String, nil] the string representation of the parameter @since 0.3.0
# File lib/glyph/macro.rb, line 42 def raw_parameter(n) @node.parameter(n).contents.to_s rescue nil end
Equivalent to Glyph::Macro#raw_parameter(0)
. @since 0.3.0
# File lib/glyph/macro.rb, line 133 def raw_value raw_parameter(0) end
@since 0.5.0 Renders a macro representation @param [Symbol, String] rep the representation to render @param [Hash] data the data to pass to the representation
# File lib/glyph/macro.rb, line 254 def render(rep=nil, data=nil) rep ||= @name data ||= @data block = Glyph::REPS[rep.to_sym] macro_error "No macro representation for '#{rep}'", e unless block instance_exec(data, &block).to_s end
# File lib/glyph/macro.rb, line 241 def snippet(key, value) @node[:document].snippet key, value end
# File lib/glyph/macro.rb, line 246 def snippet?(ident) @node[:document].snippet? ident end
Resets the name of the updated source (call before calling Macro#interpret
) @param [String] name the source name @param [String] file the source file @param [String] topic the topic file @since 0.3.0
# File lib/glyph/macro.rb, line 33 def update_source(name, file=nil, topic=nil) file ||= @node[:source][:file] rescue nil @updated_source = {:name => name, :file => file, :topic => topic} end
Equivalent to Glyph::Macro#parameter(0)
. @since 0.3.0
# File lib/glyph/macro.rb, line 127 def value parameter(0) end
Private Instance Methods
# File lib/glyph/macro.rb, line 327 def create_context context = {} context[:source] = @updated_source || @node[:source] context[:embedded] = true context[:document] = @node[:document] context end