module Erubis::PI::Converter

def self.desc # :nodoc:

:nodoc:
def self.desc   # :nodoc:
  "use processing instructions (PI) instead of '<% %>'"
end

def self.supported_properties # :nodoc:

:nodoc:
def self.supported_properties    # :nodoc:
  return [
          [:trim,      true,   "trim spaces around <% ... %>"],
          [:pi,        'rb',   "PI (Processing Instrunctions) name"],
          [:embchar,   '@',    "char for embedded expression pattern('@{...}@')"],
          [:pattern,  '<% %>', "embed pattern"],
         ]
end

def add_pi_expr(codebuf, code, indicator) # :nodoc:

:nodoc:
def add_pi_expr(codebuf, code, indicator)  # :nodoc:
  case indicator
  when nil, '', '=='    # @{...}@ or <%== ... %>
    @escape == false ? add_expr_literal(codebuf, code) : add_expr_escaped(codebuf, code)
  when '!', '='         # @!{...}@ or <%= ... %>
    @escape == false ? add_expr_escaped(codebuf, code) : add_expr_literal(codebuf, code)
  when '!!', '==='      # @!!{...}@ or <%=== ... %>
    add_expr_debug(codebuf, code)
  else
    # ignore
  end
end

def add_pi_stmt(codebuf, code, pi_arg) # :nodoc:

:nodoc:
def add_pi_stmt(codebuf, code, pi_arg)  # :nodoc:
  case pi_arg
  when nil      ;  add_stmt(codebuf, code)
  when 'header' ;  @header = code
  when 'footer' ;  @footer = code
  when 'comment';  add_stmt(codebuf, "\n" * code.count("\n"))
  when 'value'  ;  add_expr_literal(codebuf, code)
  else          ;  add_stmt(codebuf, code)
  end
end

def convert(input)

def convert(input)
  code = super(input)
  return @header || @footer ? "#{@header}#{code}#{@footer}" : code
end

def convert_input(codebuf, input)

def convert_input(codebuf, input)
  unless @regexp
    @pi ||= 'e'
    ch = Regexp.escape(@embchar)
    if @pattern
      left, right = @pattern.split(' ')
      @regexp = /<\?#{@pi}(?:-(\w+))?(\s.*?)\?>([ \t]*\r?\n)?|#{ch}(!*)?\{(.*?)\}#{ch}|#{left}(=+)(.*?)#{right}/m
    else
      @regexp = /<\?#{@pi}(?:-(\w+))?(\s.*?)\?>([ \t]*\r?\n)?|#{ch}(!*)?\{(.*?)\}#{ch}/m
    end
  end
  #
  is_bol = true
  pos = 0
  input.scan(@regexp) do |pi_arg, stmt, rspace,
                          indicator1, expr1, indicator2, expr2|
    match = Regexp.last_match
    len = match.begin(0) - pos
    text = input[pos, len]
    pos = match.end(0)
    lspace = stmt ? detect_spaces_at_bol(text, is_bol) : nil
    is_bol = stmt && rspace ? true : false
    add_text(codebuf, text) # unless text.empty?
    #
    if stmt
      if @trim && lspace && rspace
        add_pi_stmt(codebuf, "#{lspace}#{stmt}#{rspace}", pi_arg)
      else
        add_text(codebuf, lspace) if lspace
        add_pi_stmt(codebuf, stmt, pi_arg)
        add_text(codebuf, rspace) if rspace
      end
    else
      add_pi_expr(codebuf, expr1 || expr2, indicator1 || indicator2)
    end
  end
  #rest = $' || input                        # ruby1.8
  rest = pos == 0 ? input : input[pos..-1]   # ruby1.9
  add_text(codebuf, rest)
end

def init_converter(properties={})

def init_converter(properties={})
  super(properties)
  @trim    = properties.fetch(:trim, true)
  @pi      = properties[:pi] if properties[:pi]
  @embchar = properties[:embchar] || '@'
  @pattern = properties[:pattern]
  @pattern = '<% %>' if @pattern.nil?  #|| @pattern == true
end