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


3
4
5
6
# File 'lib/rouge/tex_theme_renderer.rb', line 3

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

Instance Method Details

#camelize(name) ⇒ Object


94
95
96
# File 'lib/rouge/tex_theme_renderer.rb', line 94

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

#gen_inline(name, &b) ⇒ Object


83
84
85
86
87
88
89
90
91
92
# File 'lib/rouge/tex_theme_renderer.rb', line 83

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


67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/rouge/tex_theme_renderer.rb', line 67

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


98
99
100
101
102
# File 'lib/rouge/tex_theme_renderer.rb', line 98

def palette_name(name)
  name = inline_name(name) || name.to_s

  "#{@prefix}@[email protected]#{camelize(@theme.name)}@#{camelize(name.to_s)}"
end

#render {|<<'END'.gsub('RG', @prefix) \makeatletter \def\RG#1#2{\csname [email protected]@#1\endcsname{#2}}% \newenvironment{RG*}{\ttfamily}{\relax}% END| ... } ⇒ Object

Our general strategy is this:

  • First, define the \RGtoknamecontent command, which will expand into \[email protected]@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 [email protected]@[email protected]. Then we find all foreground and background colors that have literal html colors embedded in them and define them with names such as [email protected]@[email protected]. 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 [email protected][email protected]. 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 [email protected]@#1\endcsname{#2}}% \newenvironment{RG*}{\ttfamily}{\relax}% END)

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

def render(&b)
  yield <<'END'.gsub('RG', @prefix)
\makeatletter
\def\RG#1#2{\csname [email protected]@#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


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

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

#render_inline_pallete(style, &b) ⇒ Object


62
63
64
65
# File 'lib/rouge/tex_theme_renderer.rb', line 62

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

#render_palette(palette, &b) ⇒ Object


54
55
56
57
58
59
60
# File 'lib/rouge/tex_theme_renderer.rb', line 54

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)

112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# File 'lib/rouge/tex_theme_renderer.rb', line 112

def render_style(tok, style, &b)
  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


104
105
106
# File 'lib/rouge/tex_theme_renderer.rb', line 104

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