class Rouge::TexThemeRenderer

def camelize(name)

def camelize(name)
  name.gsub(/_(.)/) { $1.upcase }
end

def gen_inline(name, &b)

def gen_inline(name, &b)
  # detect inline colors
  hex = inline_name(name)
  return unless hex
  @gen_inline ||= {}
  @gen_inline[hex] ||= begin
    yield "\\definecolor{#{palette_name(hex)}}{HTML}{#{hex}}%"
  end
end

def initialize(theme, opts={})

def initialize(theme, opts={})
  @theme = theme
  @prefix = opts.fetch(:prefix) { 'RG' }
end

def inline_name(color)

def inline_name(color)
  color =~ /^#(\h+)/ or return nil
  # xcolor does not support 3-character HTML colors,
  # so we convert them here
  case $1.size
  when 6
    $1
  when 3
    # duplicate every character: abc -> aabbcc
    $1.gsub(/\h/, '\0\0')
  else
    raise "invalid HTML color: #{$1}"
  end.upcase
end

def palette_name(name)

def palette_name(name)
  name = inline_name(name) || name.to_s
  "#{@prefix}@palette@#{camelize(@theme.name)}@#{camelize(name.to_s)}"
end

def render(&b)

in the palette.
argument and format it according to the theme, referring to the color
* Define the token commands RG@tok@xx. These will take the content as the

to normalize that as well as the case convention in #inline_name.
as #FFF, xcolor requires all six characters to be present, so we make sure
RG@palette@themename@000000. While html allows three-letter colors such
colors embedded in them and define them with names such as
Then we find all foreground and background colors that have literal html
every palette color with a name such as RG@palette@themneame@colorname.
* Define all the colors using xcolors \definecolor command. First we define

any other formatting.
but it can be overridden with \renewcommand by the user to be
thing. By default this will simply set \ttfamily (select monospace font)
* Define the default RG* environment, which will enclose the whole

to interpolate into a command.
expand into \RG@tok@tokname{content}. We use \csname...\endcsname
* First, define the \RG{tokname}{content} command, which will

Our general strategy is this:
def render(&b)
  yield <<'END'.gsub('RG', @prefix)
eatletter
\RG#1#2{\csname RG@tok@#1\endcsname{#2}}%
environment{RG*}{\ttfamily}{\relax}%
  base = @theme.class.base_style
  yield "\\definecolor{#{@prefix}@fgcolor}{HTML}{#{inline_name(base.fg || '#000000')}}"
  yield "\\definecolor{#{@prefix}@bgcolor}{HTML}{#{inline_name(base.bg || '#FFFFFF')}}"
  render_palette(@theme.palette, &b)
  @theme.styles.each do |tok, style|
    render_inline_pallete(style, &b)
  end
  Token.each_token do |tok|
    style = @theme.class.get_own_style(tok)
    style ? render_style(tok, style, &b) : render_blank(tok, &b)
  end
  yield '\makeatother'
end

def render_blank(tok, &b)

def render_blank(tok, &b)
  "\\expandafter\\def#{token_name(tok)}#1{#1}"
end

def render_inline_pallete(style, &b)

def render_inline_pallete(style, &b)
  gen_inline(style[:fg], &b)
  gen_inline(style[:bg], &b)
end

def render_palette(palette, &b)

def render_palette(palette, &b)
  palette.each do |name, color|
    hex = inline_name(color)
    yield "\\definecolor{#{palette_name(name)}}{HTML}{#{hex}}%"
  end
end

def render_style(tok, style, &b)

def render_style(tok, style, &b)
  out = String.new('')
  out << "\\expandafter\\def#{token_name(tok)}#1{"
  out << "\\fboxsep=0pt\\colorbox{#{palette_name(style[:bg])}}{" if style[:bg]
  out << '\\textbf{' if style[:bold]
  out << '\\textit{' if style[:italic]
  out << "\\textcolor{#{palette_name(style[:fg])}}{" if style[:fg]
  out << "#1"
  # close the right number of curlies
  out << "}" if style[:bold]
  out << "}" if style[:italic]
  out << "}" if style[:fg]
  out << "}" if style[:bg]
  out << "}%"
  yield out
end

def token_name(tok)

def token_name(tok)
  "\\csname #@prefix@tok@#{tok.shortname}\\endcsname"
end