Module: Polytexnic::Utils

Extended by:
Utils
Included in:
Pipeline, Utils
Defined in:
lib/polytexnic/utils.rb

Instance Method Summary collapse

Instance Method Details

#add_font_info(string) ⇒ Object

Adds some verbatim font info (including size). We prepend rather than replace the styles because the Pygments output includes a required override of the default commandchars. Since the substitution is only important in the context of a PDF book, it only gets made if there’s a style in ‘softcover.sty’ in the current directory



128
129
130
131
132
133
134
135
136
# File 'lib/polytexnic/utils.rb', line 128

def add_font_info(string)
  if File.exist?('softcover.sty')
    regex = '{code}{Verbatim}{(.*)}'
    styles = File.read('softcover.sty').scan(/#{regex}/).flatten.first
    string.gsub!("\\begin{Verbatim}[",
                 "\\begin{Verbatim}[#{styles},")
  end
  string
end

#cache_hrefs(doc, latex = false) ⇒ Object

Caches URLs for href commands.



41
42
43
44
45
46
47
48
49
# File 'lib/polytexnic/utils.rb', line 41

def cache_hrefs(doc, latex=false)
  doc.tap do |text|
    text.gsub!(/\\href{(.*?)}/) do
      key = digest($1)
      literal_cache[key] = $1
      "\\href{#{key}}"
    end
  end
end

#debug?Boolean

Returns true if we are debugging, false otherwise. Manually change to ‘true` on an as-needed basis.

Returns:

  • (Boolean)


157
158
159
# File 'lib/polytexnic/utils.rb', line 157

def debug?
  false
end

#digest(string, options = {}) ⇒ Object

Returns a salted hash digest of the string.



14
15
16
17
# File 'lib/polytexnic/utils.rb', line 14

def digest(string, options = {})
  salt = options[:salt] || SecureRandom.base64
  Digest::SHA1.hexdigest("#{salt}--#{string}")
end

#escape_backslashes(string) ⇒ Object

Escapes backslashes. Interpolated backslashes need extra escaping. We only escape ‘\’ by itself, i.e., a backslash followed by spaces or the end of line.



36
37
38
# File 'lib/polytexnic/utils.rb', line 36

def escape_backslashes(string)
  string.gsub(/\\(\s+|$)/) { '\\\\' + $1.to_s }
end

#framed(code) ⇒ Object

Puts a frame around code.



111
112
113
# File 'lib/polytexnic/utils.rb', line 111

def framed(code)
  "\\begin{framed_shaded}\n#{code}\n\\end{framed_shaded}"
end

#highlight(key, content, language, formatter) ⇒ Object

Highlights a code sample.



116
117
118
119
120
# File 'lib/polytexnic/utils.rb', line 116

def highlight(key, content, language, formatter)
  highlight_cache[key] ||= Pygments.highlight(content,
                                              lexer: language,
                                              formatter: formatter)
end

#highlight_source_code(document) ⇒ Object

Highlights source code.



87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# File 'lib/polytexnic/utils.rb', line 87

def highlight_source_code(document)
  if document.is_a?(String) # LaTeX
    substitutions = {}
    document.tap do
      code_cache.each do |key, (content, language, in_codelisting)|
        code   = highlight(key, content, language, 'latex')
        output = code.split("\n")
        horrible_backslash_kludge(add_font_info(output.first))
        code = output.join("\n")
        substitutions[key] = in_codelisting ? code : framed(code)
      end
      document.gsub!(Regexp.union(substitutions.keys), substitutions)
    end
  else # HTML
    document.css('div.code').each do |code_block|
      key = code_block.content
      next unless (value = code_cache[key])
      content, language = value
      code_block.inner_html = highlight(key, content, language, 'html')
    end
  end
end

#horrible_backslash_kludge(string) ⇒ Object

Does something horrible with backslashes. OK, so the deal is that code highlighted for LaTeX contains the line beginVerbatim Oh crap, there are backslashes in there. This means we have no chance of getting things to work after interpolating, gsubbing, and so on, because in Ruby ‘\foo’ is the same as ‘\\foo’, ‘}’ is ‘}’, etc. I thought I escaped (heh) this problem with the ‘escape_backslashes` method, but here the problem is extremely specific. In particular, \{} is really \ and { and }, but Ruby doensn’t know WTF to do with it, and thinks that it’s “\{}”, which is the same as ‘{}’. The solution is to replace ‘\\’ with some number of backslashes. How many? I literally had to just keep adding backslashes until the output was correct when running ‘poly build:pdf`.



151
152
153
# File 'lib/polytexnic/utils.rb', line 151

def horrible_backslash_kludge(string)
  string.gsub!(/commandchars=\\\\/, 'commandchars=\\\\\\\\')
end

#pipeline_digest(element) ⇒ Object

Returns a digest for passing things through the pipeline.



20
21
22
23
# File 'lib/polytexnic/utils.rb', line 20

def pipeline_digest(element)
  value = digest("#{Time.now.to_s}::#{element}")
  @literal_cache[element.to_s] ||= value
end

#profiling?Boolean

Returns true if we are profiling the code, false otherwise. Manually change to ‘true` on an as-needed basis.

Returns:

  • (Boolean)


163
164
165
166
# File 'lib/polytexnic/utils.rb', line 163

def profiling?
  return false if test?
  false
end

#set_test_mode!Object



168
169
170
# File 'lib/polytexnic/utils.rb', line 168

def set_test_mode!
  @@test_mode = true
end

#test?Boolean

Returns:

  • (Boolean)


172
173
174
# File 'lib/polytexnic/utils.rb', line 172

def test?
  defined?(@@test_mode) && @@test_mode
end

#tralicsObject

Returns the executable for the Tralics LaTeX-to-XML converter.



8
9
10
11
# File 'lib/polytexnic/utils.rb', line 8

def tralics
  File.join(File.dirname(__FILE__), '..', '..',
            'precompiled_binaries', 'tralics')
end

#tralics_commandsObject

Returns some commands for Tralics. For various reasons, we don’t actually want to include these in the style file that gets passed to LaTeX. For example, the commands with ‘xmlelt’ aren’t even valid LaTeX; they’re actually pseudo-LaTeX that has special meaning to the Tralics processor.



66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/polytexnic/utils.rb', line 66

def tralics_commands
  <<-'EOS'
% Commands specific to Tralics
\def\hyperref[#1]#2{\xmlelt{a}{\XMLaddatt{target}{#1}#2}}
\newcommand{\heading}[1]{\xmlelt{heading}{#1}}
\newcommand{\codecaption}[1]{\xmlelt{heading}{#1}}
\newcommand{\sout}[1]{\xmlelt{sout}{#1}}
\newcommand{\kode}[1]{\xmlelt{kode}{#1}}
\newcommand{\filepath}[1]{\xmlelt{filepath}{#1}}
\newcommand{\image}[1]{\xmlelt{image}{#1}}
\newcommand{\imagebox}[1]{\xmlelt{imagebox}{#1}}

% Code listings
\usepackage{amsthm}
\theoremstyle{definition}
\newtheorem{codelisting}{Listing}[chapter]
\newtheorem{aside}{Box}[chapter]
  EOS
end

#underscore_digestObject

Returns a digest for use in labels. I like to use labels of the form cha:foo_bar, but for some reason Tralics removes the underscore in this case.



28
29
30
# File 'lib/polytexnic/utils.rb', line 28

def underscore_digest
  pipeline_digest('_')
end

#xmlelement(name, skip = false) ⇒ Object

Returns a Tralics pseudo-LaTeX XML element. The use of the ‘skip’ flag is a hack to be able to use xmlelement even when generating, e.g., LaTeX, where we simply want to yield the block.



55
56
57
58
59
# File 'lib/polytexnic/utils.rb', line 55

def xmlelement(name, skip = false)
  output = (skip ? "" : "\\begin{xmlelement}{#{name}}")
  output << yield if block_given?
  output << (skip ? "" : "\\end{xmlelement}")
end