Class: Rouge::TexThemeRenderer

Inherits:
Object
  • Object
show all
Defined in:
lib/rouge/tex_theme_renderer.rb

Instance Method Summary collapse

Constructor Details

#initialize(theme, opts = {}) ⇒ TexThemeRenderer

Returns a new instance of TexThemeRenderer.



6
7
8
9
# File 'lib/rouge/tex_theme_renderer.rb', line 6

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

Instance Method Details

#camelize(name) ⇒ Object



97
98
99
# File 'lib/rouge/tex_theme_renderer.rb', line 97

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

#gen_inline(name, &b) ⇒ Object



86
87
88
89
90
91
92
93
94
95
# File 'lib/rouge/tex_theme_renderer.rb', line 86

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) ⇒ Object



70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/rouge/tex_theme_renderer.rb', line 70

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) ⇒ Object



101
102
103
104
105
# File 'lib/rouge/tex_theme_renderer.rb', line 101

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) \makeatletter \def\RG#1#2{\csname RG@tok@#1\endcsname{#2}}% \newenvironment{RG*}{\ttfamily}{\relax}% END| ... } ⇒ Object

Our general strategy is this:

  • First, define the RGtoknamecontent command, which will expand into RG@tok@toknamecontent. 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 RG@palette@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 RG@palette@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 RG@tok@xx. These will take the content as the argument and format it according to the theme, referring to the color in the palette.

Yields:

  • (<<'END'.gsub('RG', @prefix) \makeatletter \def\RG#1#2{\csname RG@tok@#1\endcsname{#2}}% \newenvironment{RG*}{\ttfamily}{\relax}% END)


33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# File 'lib/rouge/tex_theme_renderer.rb', line 33

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) ⇒ Object



111
112
113
# File 'lib/rouge/tex_theme_renderer.rb', line 111

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

#render_inline_pallete(style, &b) ⇒ Object



65
66
67
68
# File 'lib/rouge/tex_theme_renderer.rb', line 65

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

#render_palette(palette, &b) ⇒ Object



57
58
59
60
61
62
63
# File 'lib/rouge/tex_theme_renderer.rb', line 57

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| ... } ⇒ Object

Yields:

  • (out)


115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
# File 'lib/rouge/tex_theme_renderer.rb', line 115

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) ⇒ Object



107
108
109
# File 'lib/rouge/tex_theme_renderer.rb', line 107

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