Inversion::Template::CodeTag

The base class for Inversion tags that parse the body section of the tag using a Ruby parser.

It provides a tag_pattern declarative method that is used to specify a pattern of tokens to match, and a block for handling tag instances that match the pattern.

class Inversion::Template::MyTag < Inversion::Template::CodeTag

    # Match a tag that looks like: <?my "string of stuff" ?>
    tag_pattern 'tstring_beg $(tstring_content) tstring_end' do |tag, match|
        tag.string = match.string( 1 )
    end

end

The tokens in the tag_pattern are Ruby token names used by the parser. If you're creating your own tag, you can dump the tokens for a particular snippet using the 'inversion' command-line tool that comes with the gem:

$ inversion tagtokens 'attr.dump! {|thing| thing.length }'
ident<"attr"> period<"."> ident<"dump!"> sp<" "> lbrace<"{"> op<"|"> \
  ident<"thing"> op<"|"> sp<" "> ident<"thing"> period<".">          \
  ident<"length"> sp<" "> rbrace<"}">

:todo: Finish the tag_pattern docs: placeholders, regex limitations, etc.

Attributes

body[R]

the body of the tag

identifiers[R]

the identifiers in the code contained in the tag

Public Class Methods

tag_pattern( token_pattern ) click to toggle source

Declare a token_pattern for tag bodies along with a callback that will be called when a tag matching the pattern is instantiated.

# File lib/inversion/template/codetag.rb, line 95
def self::tag_pattern( token_pattern, &callback ) #:yield: 
        pattern = TokenPattern.compile( token_pattern )
        @tag_patterns = [] unless defined?( @tag_patterns )
        @tag_patterns << [ pattern, callback ]
end
tag_patterns() click to toggle source

Return the tag patterns for this class, or those of its superclass if it doesn't override them.

# File lib/inversion/template/codetag.rb, line 87
def self::tag_patterns
        return @tag_patterns if defined?( @tag_patterns )
        return self.superclass.tag_patterns
end

Protected Instance Methods

initialize( body, linenum=nil, colnum=nil ) click to toggle source

Initialize a new tag that expects Ruby code in its body. Calls the tag's parse_pi_body method with the specified body.

# File lib/inversion/template/codetag.rb, line 108
def initialize( body, linenum=nil, colnum=nil ) # :notnew:
        super

        @body = body.strip
        @identifiers = []
        @matched_pattern = self.match_tag_pattern( body )
end
match_tag_pattern( body ) click to toggle source

Match the given body against one of the tag's tag patterns, calling the block associated with the first one that matches and returning the matching pattern.

# File lib/inversion/template/codetag.rb, line 140
def match_tag_pattern( body )

        self.class.tag_patterns.each do |tp, callback|
                if match = tp.match( body.strip )
                        self.log.debug "Matched tag pattern: %p, match is: %p" % [ tp, match ]
                        callback.call( self, match )
                        return tp
                end
        end

        self.log.error "Failed to match %p with %d patterns." %
                [ body, self.class.tag_patterns.length ]

        valid_patterns = self.class.tag_patterns.map( &:first ).map( &:source ).join( "\n  ")
        tokenized_src = Ripper.lex( body ).collect do |tok|
                self.log.debug "  lexed token: #{tok.inspect}"
                "%s<%s>" % [ tok[1].to_s[3..-1], tok[2] ]
        end.join(' ')

        raise Inversion::ParseError, "malformed %s: expected one of:\n  %s\ngot:\n  %s" %
                [ self.tagname, valid_patterns, tokenized_src ]
end

[Validate]

Generated with the Darkfish Rdoc Generator 2.