class Rouge::TexThemeRenderer

Public Class Methods

new(theme, opts={}) click to toggle source
# File lib/rouge/tex_theme_renderer.rb, line 5
def initialize(theme, opts={})
  @theme = theme
  @prefix = opts.fetch(:prefix) { 'RG' }
end

Public Instance Methods

camelize(name) click to toggle source
# File lib/rouge/tex_theme_renderer.rb, line 96
def camelize(name)
  name.gsub(/_(.)/) { $1.upcase }
end
gen_inline(name) { |"\\definecolor{#{palette_name(hex)}}{HTML}{#{hex}}%"| ... } click to toggle source
# File lib/rouge/tex_theme_renderer.rb, line 85
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
inline_name(color) click to toggle source
# File lib/rouge/tex_theme_renderer.rb, line 69
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
palette_name(name) click to toggle source
# File lib/rouge/tex_theme_renderer.rb, line 100
def palette_name(name)
  name = inline_name(name) || name.to_s

  "#{@prefix}@palette@#{camelize(@theme.name)}@#{camelize(name.to_s)}"
end
render() { |<<'END'.gsub('RG', prefix)| ... } click to toggle source

Our general strategy is this:

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

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

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

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

# File lib/rouge/tex_theme_renderer.rb, line 32
    def render(&b)
      yield <<'END'.gsub('RG', @prefix)
\makeatletter
\def\RG#1#2{\csname RG@tok@#1\endcsname{#2}}%
\newenvironment{RG*}{\ttfamily}{\relax}%
END

      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
render_blank(tok, &b) click to toggle source
# File lib/rouge/tex_theme_renderer.rb, line 110
def render_blank(tok, &b)
  out = "\\expandafter\\def#{token_name(tok)}#1{#1}"
end
render_inline_pallete(style, &b) click to toggle source
# File lib/rouge/tex_theme_renderer.rb, line 64
def render_inline_pallete(style, &b)
  gen_inline(style[:fg], &b)
  gen_inline(style[:bg], &b)
end
render_palette(palette) { |"\\definecolor{#{palette_name(name)}}{HTML}{#{hex}}%"| ... } click to toggle source
# File lib/rouge/tex_theme_renderer.rb, line 56
def render_palette(palette, &b)
  palette.each do |name, color|
    hex = inline_name(color)

    yield "\\definecolor{#{palette_name(name)}}{HTML}{#{hex}}%"
  end
end
render_style(tok, style) { |out| ... } click to toggle source
# File lib/rouge/tex_theme_renderer.rb, line 114
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
token_name(tok) click to toggle source
# File lib/rouge/tex_theme_renderer.rb, line 106
def token_name(tok)
  "\\csname #@prefix@tok@#{tok.shortname}\\endcsname"
end