from .formats import BaseFormat from .tokens import * # These are done in order, so make sure they don't interfere with each other QUOTE_MAP = ( ('\\',r'\textbackslash '), # This should almost certainly be first ('{',r'\{'), ('}',r'\}'), # Anything with {}-delimited arguments goes after here ('%',r'\%'), ('&',r'\&'), ('$',r'\$'), ('#',r'\#'), ('_',r'\_'), ('~',r'\~{}'), ('^',r'\^{}'), ('<',r'$<$'), ('>',r'$>$'), ('[',r'{[}'), # Needed, say, right after \item (']',r'{]}'), # Needed /in/ an optional argument, for example \item[{]}] ("'",r'\textquotesingle'), # To keep from smarting, since we do that above ('"',r'\textquotedbl'), ) CMD_MAP = {BOLD: 'textbf', ITALIC: 'emph', MONOSPACE: 'texttt', SUPERSCRIPT: 'textsuperscript', SUBSCRIPT: 'textsubscript', UNDERLINE: 'uline', STRIKE: 'sout', FOOTNOTE: 'footnote', } ENV_MAP = {CENTER: 'center'} LATEX_HEADINGS = { 1: r'chapter', 2: r'section', 3: r'subsection', 4: r'subsubsection', 5: r'subsubsubsection', 6: r'paragraph' } LISTMAP = {ORDERED: 'enumerate', UNORDERED: 'itemize', BLOCKQUOTE: 'quotation', } class LaTeXFormat(BaseFormat): def __init__(self): self.verbatim = False def escape(self, text): if self.verbatim: return text else: for bad,repl in QUOTE_MAP: text = text.replace(bad,repl) return text def text(self, text): return self.escape(text) def error(self, text): return r'\error{%s}' % self.escape(text) def start(self, t, arg=None): if t in CMD_MAP: return ur'\%s{' % CMD_MAP[t] elif t in ENV_MAP: return u'\\begin{%s}\n' % ENV_MAP[t] elif t in LISTMAP: return u'\\begin{%s}\n' % LISTMAP[t] elif t in (ORDERED_ITEM, UNORDERED_ITEM): return ur'\item ' elif t == BLOCKQUOTE_LINE: return '' elif t == PARAGRAPH: return '' elif t == LINK: return ur'\href{%s}{' % (self.escape(arg['url'])) elif t == HEADING: return ur'\%s{' % LATEX_HEADINGS[arg] elif t == CODEBLOCK: self.verbatim = True return u'\\begin{verbatim}\n' else: return self.tag(t, arg) def end(self, t, arg=None): if t in CMD_MAP: return u'}' elif t in ENV_MAP: return u'\n\\end{%s}' % ENV_MAP[t] elif t in LISTMAP: return u'\\end{%s}\n' % LISTMAP[t] elif t in (ORDERED_ITEM, UNORDERED_ITEM, BLOCKQUOTE_LINE): return '\n' elif t == PARAGRAPH: return '' elif t in (LINK, HEADING): return '}' elif t == CODEBLOCK: self.verbatim = False return u'\n\end{verbatim}' else: return self.tag(t, arg) def entity(self, t, arg=None): if t == HRULE: return u'\hrule' elif t == LINEBREAK: return u'\\\\' elif t == ENV_BREAK: return u'\n\n' def image(self, href, state, alt=None, info={}): # This only works because of the magic image fetching logic # that bazki.latex does. assert '://' in href path = href.split('://', 1)[1].replace('^', '--').replace(' ', '_') args = [] if 'height' in info: args.append('height=%spx' % info['height']) if 'width' in info: args.append('width=%spx' % info['width']) if len(args) > 0: argstr = '[%s]' % ','.join(args) else: argstr = '' yield '\n\\includegraphics%s{%s}\n' % (argstr, path)