PageRenderTime 64ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/sandbox/rst2context/context/__init__.py

https://bitbucket.org/mirror/docutils
Python | 3049 lines | 3006 code | 10 blank | 33 comment | 7 complexity | d03c58fb861dfc4bbb244889ca5878f2 MD5 | raw file
Possible License(s): Apache-2.0, BSD-2-Clause, GPL-3.0, GPL-2.0, MIT

Large files files are truncated, but you can click here to view the full file

  1. # .. coding: utf8
  2. # $Id$
  3. # Author: Engelbert Gruber <grubert@users.sourceforge.net>
  4. # Copyright: This module has been placed in the public domain.
  5. """ConTeXt document tree Writer."""
  6. __docformat__ = 'reStructuredText'
  7. # code contributions from several people included, thanks to all.
  8. # some named: David Abrahams, Julien Letessier, Lele Gaifax, and others.
  9. #
  10. # convention deactivate code by two # i.e. ##.
  11. import sys
  12. import os
  13. import time
  14. import re
  15. import string
  16. import urllib
  17. from docutils import frontend, nodes, languages, writers, utils, io
  18. from docutils.transforms import writer_aux
  19. from docutils.math import pick_math_environment, unichar2tex
  20. # compatibility module for Python 2.3
  21. if not hasattr(string, 'Template'):
  22. import docutils._string_template_compat
  23. string.Template = docutils._string_template_compat.Template
  24. class Writer(writers.Writer):
  25. supported = ('context',)
  26. """Formats this writer supports."""
  27. default_template = 'default.tex'
  28. default_template_path = os.path.dirname(__file__)
  29. default_preamble = '\n'.join([r'% PDF Standard Fonts',
  30. r'\usepackage{mathptmx} % Times',
  31. r'\usepackage[scaled=.90]{helvet}',
  32. r'\usepackage{courier}'])
  33. settings_spec = (
  34. 'LaTeX-Specific Options',
  35. None,
  36. (('Specify documentclass. Default is "article".',
  37. ['--documentclass'],
  38. {'default': 'article', }),
  39. ('Specify document options. Multiple options can be given, '
  40. 'separated by commas. Default is "a4paper".',
  41. ['--documentoptions'],
  42. {'default': 'a4paper', }),
  43. ('Footnotes with numbers/symbols by Docutils. (default)',
  44. ['--docutils-footnotes'],
  45. {'default': True, 'action': 'store_true',
  46. 'validator': frontend.validate_boolean}),
  47. ('Alias for --docutils-footnotes (deprecated)',
  48. ['--use-latex-footnotes'],
  49. {'action': 'store_true',
  50. 'validator': frontend.validate_boolean}),
  51. ('Use figure floats for footnote text (deprecated)',
  52. ['--figure-footnotes'],
  53. {'action': 'store_true',
  54. 'validator': frontend.validate_boolean}),
  55. ('Format for footnote references: one of "superscript" or '
  56. '"brackets". Default is "superscript".',
  57. ['--footnote-references'],
  58. {'choices': ['superscript', 'brackets'], 'default': 'superscript',
  59. 'metavar': '<format>',
  60. 'overrides': 'trim_footnote_reference_space'}),
  61. ('Use \\cite command for citations. ',
  62. ['--use-latex-citations'],
  63. {'default': 0, 'action': 'store_true',
  64. 'validator': frontend.validate_boolean}),
  65. ('Use figure floats for citations '
  66. '(might get mixed with real figures). (default)',
  67. ['--figure-citations'],
  68. {'dest': 'use_latex_citations', 'action': 'store_false',
  69. 'validator': frontend.validate_boolean}),
  70. ('Format for block quote attributions: one of "dash" (em-dash '
  71. 'prefix), "parentheses"/"parens", or "none". Default is "dash".',
  72. ['--attribution'],
  73. {'choices': ['dash', 'parentheses', 'parens', 'none'],
  74. 'default': 'dash', 'metavar': '<format>'}),
  75. ('Specify LaTeX packages/stylesheets. '
  76. ' A style is referenced with \\usepackage if extension is '
  77. '".sty" or omitted and with \\input else. '
  78. ' Overrides previous --stylesheet and --stylesheet-path settings.',
  79. ['--stylesheet'],
  80. {'default': '', 'metavar': '<file>',
  81. 'overrides': 'stylesheet_path'}),
  82. ('Like --stylesheet, but the path is rewritten '
  83. 'relative to the output file. ',
  84. ['--stylesheet-path'],
  85. {'metavar': '<file>', 'overrides': 'stylesheet'}),
  86. ('Link to the stylesheet(s) in the output file. (default)',
  87. ['--link-stylesheet'],
  88. {'dest': 'embed_stylesheet', 'action': 'store_false'}),
  89. ('Embed the stylesheet(s) in the output file. '
  90. 'Stylesheets must be accessible during processing. ',
  91. ['--embed-stylesheet'],
  92. {'default': 0, 'action': 'store_true',
  93. 'validator': frontend.validate_boolean}),
  94. ('Customization by LaTeX code in the preamble. '
  95. 'Default: select PDF standard fonts (Times, Helvetica, Courier).',
  96. ['--context-preamble'],
  97. {'default': default_preamble}),
  98. ('Specify the template file. Default: "%s".' % default_template,
  99. ['--template'],
  100. {'default': default_template, 'metavar': '<file>'}),
  101. ('Table of contents by LaTeX. (default) ',
  102. ['--use-latex-toc'],
  103. {'default': 1, 'action': 'store_true',
  104. 'validator': frontend.validate_boolean}),
  105. ('Table of contents by Docutils (without page numbers). ',
  106. ['--use-docutils-toc'],
  107. {'dest': 'use_latex_toc', 'action': 'store_false',
  108. 'validator': frontend.validate_boolean}),
  109. ('Add parts on top of the section hierarchy.',
  110. ['--use-part-section'],
  111. {'default': 0, 'action': 'store_true',
  112. 'validator': frontend.validate_boolean}),
  113. ('Attach author and date to the document info table. (default) ',
  114. ['--use-docutils-docinfo'],
  115. {'dest': 'use_latex_docinfo', 'action': 'store_false',
  116. 'validator': frontend.validate_boolean}),
  117. ('Attach author and date to the document title.',
  118. ['--use-latex-docinfo'],
  119. {'default': 0, 'action': 'store_true',
  120. 'validator': frontend.validate_boolean}),
  121. ("Typeset abstract as topic. (default)",
  122. ['--topic-abstract'],
  123. {'dest': 'use_latex_abstract', 'action': 'store_false',
  124. 'validator': frontend.validate_boolean}),
  125. ("Use LaTeX abstract environment for the document's abstract. ",
  126. ['--use-latex-abstract'],
  127. {'default': 0, 'action': 'store_true',
  128. 'validator': frontend.validate_boolean}),
  129. ('Color of any hyperlinks embedded in text '
  130. '(default: "blue", "false" to disable).',
  131. ['--hyperlink-color'], {'default': 'blue'}),
  132. ('Additional options to the "hyperref" package '
  133. '(default: "").',
  134. ['--hyperref-options'], {'default': ''}),
  135. ('Enable compound enumerators for nested enumerated lists '
  136. '(e.g. "1.2.a.ii"). Default: disabled.',
  137. ['--compound-enumerators'],
  138. {'default': None, 'action': 'store_true',
  139. 'validator': frontend.validate_boolean}),
  140. ('Disable compound enumerators for nested enumerated lists. '
  141. 'This is the default.',
  142. ['--no-compound-enumerators'],
  143. {'action': 'store_false', 'dest': 'compound_enumerators'}),
  144. ('Enable section ("." subsection ...) prefixes for compound '
  145. 'enumerators. This has no effect without --compound-enumerators.'
  146. 'Default: disabled.',
  147. ['--section-prefix-for-enumerators'],
  148. {'default': None, 'action': 'store_true',
  149. 'validator': frontend.validate_boolean}),
  150. ('Disable section prefixes for compound enumerators. '
  151. 'This is the default.',
  152. ['--no-section-prefix-for-enumerators'],
  153. {'action': 'store_false', 'dest': 'section_prefix_for_enumerators'}),
  154. ('Set the separator between section number and enumerator '
  155. 'for compound enumerated lists. Default is "-".',
  156. ['--section-enumerator-separator'],
  157. {'default': '-', 'metavar': '<char>'}),
  158. ('When possibile, use the specified environment for literal-blocks. '
  159. 'Default is quoting of whitespace and special chars.',
  160. ['--literal-block-env'],
  161. {'default': ''}),
  162. ('When possibile, use verbatim for literal-blocks. '
  163. 'Compatibility alias for "--literal-block-env=verbatim".',
  164. ['--use-verbatim-when-possible'],
  165. {'default': 0, 'action': 'store_true',
  166. 'validator': frontend.validate_boolean}),
  167. ('Table style. "standard" with horizontal and vertical lines, '
  168. '"booktabs" (LaTeX booktabs style) only horizontal lines '
  169. 'above and below the table and below the header or "borderless". '
  170. 'Default: "standard"',
  171. ['--table-style'],
  172. {'choices': ['standard', 'booktabs','nolines', 'borderless'],
  173. 'default': 'standard',
  174. 'metavar': '<format>'}),
  175. ('LaTeX graphicx package option. '
  176. 'Possible values are "dvips", "pdftex". "auto" includes LaTeX code '
  177. 'to use "pdftex" if processing with pdf(la)tex and dvips otherwise. '
  178. 'Default is no option.',
  179. ['--graphicx-option'],
  180. {'default': ''}),
  181. ('Per default the latex-writer puts the reference title into '
  182. 'hyperreferences. Specify "ref*" or "pageref*" to get the section '
  183. 'number or the page number.',
  184. ['--reference-label'],
  185. {'default': None, }),
  186. ('Specify style and database for bibtex, for example '
  187. '"--use-bibtex=mystyle,mydb1,mydb2".',
  188. ['--use-bibtex'],
  189. {'default': None, }),
  190. ),)
  191. settings_defaults = {'sectnum_depth': 0 # updated by SectNum transform
  192. }
  193. relative_path_settings = ('stylesheet_path',)
  194. config_section = 'context writer'
  195. config_section_dependencies = ('writers',)
  196. head_parts = ('head_prefix', 'requirements', 'context_preamble', 'latex_preamble',
  197. 'stylesheet', 'fallbacks', 'pdfsetup',
  198. 'title', 'subtitle', 'titledata')
  199. visitor_attributes = head_parts + ('body_pre_docinfo', 'docinfo',
  200. 'dedication', 'abstract', 'body')
  201. output = None
  202. """Final translated form of `document`."""
  203. def __init__(self):
  204. writers.Writer.__init__(self)
  205. self.translator_class = LaTeXTranslator
  206. # Override parent method to add latex-specific transforms
  207. def get_transforms(self):
  208. # call the parent class' method
  209. transform_list = writers.Writer.get_transforms(self)
  210. # print transform_list
  211. # Convert specific admonitions to generic one
  212. transform_list.append(writer_aux.Admonitions)
  213. # TODO: footnote collection transform
  214. # transform_list.append(footnotes.collect)
  215. return transform_list
  216. def translate(self):
  217. visitor = self.translator_class(self.document)
  218. self.document.walkabout(visitor)
  219. # copy parts
  220. for part in self.visitor_attributes:
  221. setattr(self, part, getattr(visitor, part))
  222. # get template string from file
  223. try:
  224. template_file = open(self.document.settings.template, 'rb')
  225. except IOError:
  226. template_file = open(os.path.join(self.default_template_path,
  227. self.document.settings.template), 'rb')
  228. template = string.Template(unicode(template_file.read(), 'utf-8'))
  229. template_file.close()
  230. # fill template
  231. self.assemble_parts() # create dictionary of parts
  232. self.output = template.substitute(self.parts)
  233. def assemble_parts(self):
  234. """Assemble the `self.parts` dictionary of output fragments."""
  235. writers.Writer.assemble_parts(self)
  236. for part in self.visitor_attributes:
  237. lines = getattr(self, part)
  238. # Temporary!!! -- disable requirements
  239. if part in self.head_parts and not 'requirements':
  240. if lines:
  241. lines.append('') # to get a trailing newline
  242. self.parts[part] = '\n'.join(lines)
  243. else:
  244. # body contains inline elements, so join without newline
  245. self.parts[part] = ''.join(lines)
  246. class Babel(object):
  247. """Language specifics for LaTeX."""
  248. # TeX (babel) language names:
  249. # ! not all of these are supported by Docutils!
  250. #
  251. # based on LyX' languages file with adaptions to `BCP 47`_
  252. # (http://www.rfc-editor.org/rfc/bcp/bcp47.txt) and
  253. # http://www.tug.org/TUGboat/Articles/tb29-3/tb93miklavec.pdf
  254. # * the key without subtags is the default
  255. # * case is ignored
  256. # cf. http://docutils.sourceforge.net/docs/howto/i18n.html
  257. # http://www.w3.org/International/articles/language-tags/
  258. # and http://www.iana.org/assignments/language-subtag-registry
  259. language_codes = {
  260. # code TeX/Babel-name comment
  261. 'af': 'afrikaans',
  262. 'ar': 'arabic',
  263. # 'be': 'belarusian',
  264. 'bg': 'bulgarian',
  265. 'br': 'breton',
  266. 'ca': 'catalan',
  267. # 'cop': 'coptic',
  268. 'cs': 'czech',
  269. 'cy': 'welsh',
  270. 'da': 'danish',
  271. 'de': 'ngerman', # new spelling (de_1996)
  272. 'de_1901': 'german', # old spelling
  273. 'de_at': 'naustrian',
  274. 'de_at_1901': 'austrian',
  275. 'dsb': 'lowersorbian',
  276. 'el': 'greek', # monotonic (el-monoton)
  277. 'el_polyton': 'polutonikogreek',
  278. 'en': 'english', # TeX' default language
  279. 'en_au': 'australian',
  280. 'en_ca': 'canadian',
  281. 'en_gb': 'british',
  282. 'en_nz': 'newzealand',
  283. 'en_us': 'american',
  284. 'eo': 'esperanto', # '^' is active
  285. 'es': 'spanish',
  286. 'et': 'estonian',
  287. 'eu': 'basque',
  288. # 'fa': 'farsi',
  289. 'fi': 'finnish',
  290. 'fr': 'french',
  291. 'fr_ca': 'canadien',
  292. 'ga': 'irish', # Irish Gaelic
  293. # 'grc': # Ancient Greek
  294. 'grc_ibycus': 'ibycus', # Ibycus encoding
  295. 'gl': 'galician',
  296. 'he': 'hebrew',
  297. 'hr': 'croatian',
  298. 'hsb': 'uppersorbian',
  299. 'hu': 'magyar',
  300. 'ia': 'interlingua',
  301. 'id': 'bahasai', # Bahasa (Indonesian)
  302. 'is': 'icelandic',
  303. 'it': 'italian',
  304. 'ja': 'japanese',
  305. 'kk': 'kazakh',
  306. 'la': 'latin',
  307. 'lt': 'lithuanian',
  308. 'lv': 'latvian',
  309. 'mn': 'mongolian', # Mongolian, Cyrillic script (mn-cyrl)
  310. 'ms': 'bahasam', # Bahasa (Malay)
  311. 'nb': 'norsk', # Norwegian Bokmal
  312. 'nl': 'dutch',
  313. 'nn': 'nynorsk', # Norwegian Nynorsk
  314. 'no': 'norsk', # Norwegian Bokmal
  315. 'pl': 'polish',
  316. 'pt': 'portuges',
  317. 'pt_br': 'brazil',
  318. 'ro': 'romanian',
  319. 'ru': 'russian', # '"' is active
  320. 'se': 'samin', # North Sami
  321. # sh-cyrl: Serbo-Croatian, Cyrillic script
  322. 'sh-latn': 'serbian', # Serbo-Croatian, Latin script
  323. 'sk': 'slovak',
  324. 'sl': 'slovene',
  325. 'sq': 'albanian',
  326. # 'sr-cyrl': Serbian, Cyrillic script (sr-cyrl)
  327. 'sr-latn': 'serbian', # Serbian, Latin script, " active.
  328. 'sv': 'swedish',
  329. # 'th': 'thai',
  330. 'tr': 'turkish',
  331. 'uk': 'ukrainian',
  332. 'vi': 'vietnam',
  333. # zh-latn: Chinese Pinyin
  334. }
  335. warn_msg = 'Language "%s" not supported by LaTeX (babel)'
  336. def __init__(self, language_code, reporter=None):
  337. self.reporter = reporter
  338. self.language = self.language_name(language_code)
  339. self.otherlanguages = {}
  340. self.quote_index = 0
  341. self.quotes = ('``', "''")
  342. # language dependent configuration:
  343. # double quotes are "active" in some languages (e.g. German).
  344. self.literal_double_quote = u'"'
  345. if self.language in ('ngerman', 'german', 'austrian', 'naustrian',
  346. 'russian'):
  347. self.quotes = (r'\glqq{}', r'\grqq{}')
  348. self.literal_double_quote = ur'\dq{}'
  349. if self.language == 'french':
  350. self.quotes = (r'\og{}', r'\fg{}')
  351. if self.language == 'italian':
  352. self.literal_double_quote = ur'{\char`\"}'
  353. def __call__(self):
  354. """Return the babel call with correct options and settings"""
  355. languages = self.otherlanguages.keys()
  356. languages.append(self.language or 'english')
  357. self.setup = [r'\usepackage[%s]{babel}' % ','.join(languages)]
  358. if 'spanish' in languages:
  359. # reset active chars to the original meaning:
  360. self.setup.append(
  361. r'\addto\shorthandsspanish{\spanishdeactivate{."~<>}}')
  362. # or prepend r'\def\spanishoptions{es-noshorthands}'
  363. if (languages[-1] is 'english' and
  364. 'french' in self.otherlanguages.keys()):
  365. self.setup += ['% Prevent side-effects if French hyphenation '
  366. 'patterns are not loaded:',
  367. r'\frenchbsetup{StandardLayout}',
  368. r'\AtBeginDocument{\selectlanguage{%s}'
  369. r'\noextrasfrench}' % self.language]
  370. return '\n'.join(self.setup)
  371. def next_quote(self):
  372. q = self.quotes[self.quote_index]
  373. self.quote_index = (self.quote_index+1) % 2
  374. return q
  375. def quote_quotes(self,text):
  376. t = None
  377. for part in text.split('"'):
  378. if t == None:
  379. t = part
  380. else:
  381. t += self.next_quote() + part
  382. return t
  383. def language_name(self, language_code):
  384. """Return TeX language name for `language_code`"""
  385. for tag in utils.normalize_language_tag(language_code):
  386. try:
  387. return self.language_codes[tag]
  388. except KeyError:
  389. pass
  390. if self.reporter is not None:
  391. self.reporter.warning(self.warn_msg % language_code)
  392. return ''
  393. def get_language(self):
  394. """Return `self.language` (for backwards compatibility with Sphinx).
  395. """
  396. return self.language
  397. # Building blocks for the context preamble
  398. # --------------------------------------
  399. class SortableDict(dict):
  400. """Dictionary with additional sorting methods
  401. Tip: use key starting with with '_' for sorting before small letters
  402. and with '~' for sorting after small letters.
  403. """
  404. def sortedkeys(self):
  405. """Return sorted list of keys"""
  406. keys = self.keys()
  407. keys.sort()
  408. return keys
  409. def sortedvalues(self):
  410. """Return list of values sorted by keys"""
  411. return [self[key] for key in self.sortedkeys()]
  412. # PreambleCmds
  413. # `````````````
  414. # A container for LaTeX code snippets that can be
  415. # inserted into the preamble if required in the document.
  416. #
  417. # .. The package 'makecmds' would enable shorter definitions using the
  418. # \providelength and \provideenvironment commands.
  419. # However, it is pretty non-standard (texlive-latex-extra).
  420. class PreambleCmds(object):
  421. """Building blocks for the latex preamble."""
  422. PreambleCmds.abstract = r"""
  423. % abstract title
  424. \providecommand*{\DUtitleabstract}[1]{\centerline{{\bf #1}}}"""
  425. PreambleCmds.admonition = r"""
  426. % admonition (specially marked topic)
  427. \providecommand{\DUadmonition}[2][class-arg]{%
  428. % try \DUadmonition#1{#2}:
  429. \ifcsname DUadmonition#1\endcsname%
  430. \csname DUadmonition#1\endcsname{#2}%
  431. \else
  432. \begin{center}
  433. \fbox{\parbox{0.9\textwidth}{#2}}
  434. \end{center}
  435. \fi
  436. }"""
  437. PreambleCmds.align_center = r"""
  438. \makeatletter
  439. \@namedef{DUrolealign-center}{\centering}
  440. \makeatother
  441. """
  442. ## PreambleCmds.caption = r"""% configure caption layout
  443. ## \usepackage{caption}
  444. ## \captionsetup{singlelinecheck=false}% no exceptions for one-liners"""
  445. PreambleCmds.color = r"""\usepackage{color}"""
  446. PreambleCmds.docinfo = r"""
  447. % docinfo (width of docinfo table)
  448. \DUprovidelength{\DUdocinfowidth}{0.9\textwidth}"""
  449. # PreambleCmds.docinfo._depends = 'providelength'
  450. PreambleCmds.embedded_package_wrapper = r"""\makeatletter
  451. %% embedded stylesheet: %s
  452. %s
  453. \makeatother"""
  454. PreambleCmds.dedication = r"""
  455. % dedication topic
  456. \providecommand{\DUtopicdedication}[1]{\begin{center}#1\end{center}}"""
  457. PreambleCmds.error = r"""
  458. % error admonition title
  459. \providecommand*{\DUtitleerror}[1]{\DUtitle{\color{red}#1}}"""
  460. # PreambleCmds.errortitle._depends = 'color'
  461. PreambleCmds.fieldlist = r"""
  462. % fieldlist environment
  463. \ifthenelse{\isundefined{\DUfieldlist}}{
  464. \newenvironment{DUfieldlist}%
  465. {\quote\description}
  466. {\enddescription\endquote}
  467. }{}"""
  468. PreambleCmds.float_settings = r"""\usepackage{float} % float configuration
  469. \floatplacement{figure}{H} % place figures here definitely"""
  470. PreambleCmds.footnotes = r"""% numeric or symbol footnotes with hyperlinks
  471. \providecommand*{\DUfootnotemark}[3]{%
  472. \raisebox{1em}{\hypertarget{#1}{}}%
  473. \hyperlink{#2}{\textsuperscript{#3}}%
  474. }
  475. \providecommand{\DUfootnotetext}[4]{%
  476. \begingroup%
  477. \renewcommand{\thefootnote}{%
  478. \protect\raisebox{1em}{\protect\hypertarget{#1}{}}%
  479. \protect\hyperlink{#2}{#3}}%
  480. \footnotetext{#4}%
  481. \endgroup%
  482. }"""
  483. PreambleCmds.footnote_floats = r"""% settings for footnotes as floats:
  484. \setlength{\floatsep}{0.5em}
  485. \setlength{\textfloatsep}{\fill}
  486. \addtolength{\textfloatsep}{3em}
  487. \renewcommand{\textfraction}{0.5}
  488. \renewcommand{\topfraction}{0.5}
  489. \renewcommand{\bottomfraction}{0.5}
  490. \setcounter{totalnumber}{50}
  491. \setcounter{topnumber}{50}
  492. \setcounter{bottomnumber}{50}"""
  493. PreambleCmds.graphicx_auto = r"""% Check output format
  494. \ifx\pdftexversion\undefined
  495. \usepackage{graphicx}
  496. \else
  497. \usepackage[pdftex]{graphicx}
  498. \fi'))"""
  499. PreambleCmds.inline = r"""
  500. % inline markup (custom roles)
  501. % \DUrole{#1}{#2} tries \DUrole#1{#2}
  502. \providecommand*{\DUrole}[2]{%
  503. \ifcsname DUrole#1\endcsname%
  504. \csname DUrole#1\endcsname{#2}%
  505. \else% backwards compatibility: try \docutilsrole#1{#2}
  506. \ifcsname docutilsrole#1\endcsname%
  507. \csname docutilsrole#1\endcsname{#2}%
  508. \else%
  509. #2%
  510. \fi%
  511. \fi%
  512. }"""
  513. PreambleCmds.legend = r"""
  514. % legend environment
  515. \ifthenelse{\isundefined{\DUlegend}}{
  516. \newenvironment{DUlegend}{\small}{}
  517. }{}"""
  518. PreambleCmds.lineblock = r"""
  519. % lineblock environment
  520. \DUprovidelength{\DUlineblockindent}{2.5em}
  521. \ifthenelse{\isundefined{\DUlineblock}}{
  522. \newenvironment{DUlineblock}[1]{%
  523. \list{}{\setlength{\partopsep}{\parskip}
  524. \addtolength{\partopsep}{\baselineskip}
  525. \setlength{\topsep}{0pt}
  526. \setlength{\itemsep}{0.15\baselineskip}
  527. \setlength{\parsep}{0pt}
  528. \setlength{\leftmargin}{#1}}
  529. \raggedright
  530. }
  531. {\endlist}
  532. }{}"""
  533. # PreambleCmds.lineblock._depends = 'providelength'
  534. PreambleCmds.linking = r"""
  535. %% hyperlinks:
  536. \ifthenelse{\isundefined{\hypersetup}}{
  537. \usepackage[%s]{hyperref}
  538. \urlstyle{same} %% normal text font (alternatives: tt, rm, sf)
  539. }{}"""
  540. PreambleCmds.minitoc = r"""%% local table of contents
  541. \usepackage{minitoc}"""
  542. PreambleCmds.optionlist = r"""
  543. % optionlist environment
  544. \providecommand*{\DUoptionlistlabel}[1]{\bf #1 \hfill}
  545. \DUprovidelength{\DUoptionlistindent}{3cm}
  546. \ifthenelse{\isundefined{\DUoptionlist}}{
  547. \newenvironment{DUoptionlist}{%
  548. \list{}{\setlength{\labelwidth}{\DUoptionlistindent}
  549. \setlength{\rightmargin}{1cm}
  550. \setlength{\leftmargin}{\rightmargin}
  551. \addtolength{\leftmargin}{\labelwidth}
  552. \addtolength{\leftmargin}{\labelsep}
  553. \renewcommand{\makelabel}{\DUoptionlistlabel}}
  554. }
  555. {\endlist}
  556. }{}"""
  557. # PreambleCmds.optionlist._depends = 'providelength'
  558. PreambleCmds.providelength = r"""
  559. % providelength (provide a length variable and set default, if it is new)
  560. \providecommand*{\DUprovidelength}[2]{
  561. \ifthenelse{\isundefined{#1}}{\newlength{#1}\setlength{#1}{#2}}{}
  562. }"""
  563. PreambleCmds.rubric = r"""
  564. % rubric (informal heading)
  565. \providecommand*{\DUrubric}[2][class-arg]{%
  566. \subsubsection*{\centering\textit{\textmd{#2}}}}"""
  567. PreambleCmds.sidebar = r"""
  568. % sidebar (text outside the main text flow)
  569. \providecommand{\DUsidebar}[2][class-arg]{%
  570. \begin{center}
  571. \colorbox[gray]{0.80}{\parbox{0.9\textwidth}{#2}}
  572. \end{center}
  573. }"""
  574. PreambleCmds.subtitle = r"""
  575. % subtitle (for topic/sidebar)
  576. \providecommand*{\DUsubtitle}[2][class-arg]{\par\emph{#2}\smallskip}"""
  577. PreambleCmds.table = r"""\usepackage{longtable,ltcaption,array}
  578. \setlength{\extrarowheight}{2pt}
  579. \newlength{\DUtablewidth} % internal use in tables"""
  580. # Options [force,almostfull] prevent spurious error messages, see
  581. # de.comp.text.tex/2005-12/msg01855
  582. PreambleCmds.textcomp = """\
  583. \\usepackage{textcomp} % text symbol macros"""
  584. PreambleCmds.titlereference = r"""
  585. % titlereference role
  586. \providecommand*{\DUroletitlereference}[1]{\textsl{#1}}"""
  587. PreambleCmds.title = r"""
  588. % title for topics, admonitions and sidebar
  589. \providecommand*{\DUtitle}[2][class-arg]{%
  590. % call \DUtitle#1{#2} if it exists:
  591. \ifcsname DUtitle#1\endcsname%
  592. \csname DUtitle#1\endcsname{#2}%
  593. \else
  594. \smallskip\noindent{\bf #2}\smallskip%
  595. \fi
  596. }"""
  597. PreambleCmds.topic = r"""
  598. % topic (quote with heading)
  599. \providecommand{\DUtopic}[2][class-arg]{%
  600. \ifcsname DUtopic#1\endcsname%
  601. \csname DUtopic#1\endcsname{#2}%
  602. \else
  603. \begin{quote}#2\end{quote}
  604. \fi
  605. }"""
  606. PreambleCmds.transition = r"""
  607. % transition (break, fancybreak, anonymous section)
  608. \providecommand*{\DUtransition}[1][class-arg]{%
  609. \hspace*{\fill}\hrulefill\hspace*{\fill}
  610. \vskip 0.5\baselineskip
  611. }"""
  612. class DocumentClass(object):
  613. """Details of a LaTeX document class."""
  614. def __init__(self, document_class, with_part=False):
  615. self.document_class = document_class
  616. self._with_part = with_part
  617. self.sections = ['section', 'subsection',
  618. 'subsubsection', 'subsubsubsection']
  619. self.sections_numbered = ['part', 'chapter', 'section', 'subsection',
  620. 'subsubsection', 'subsubsubsection',
  621. 'subsubsubsubsection']
  622. self.sections_unnumbered = ['title', 'subject', 'subsubject',
  623. 'subsubsubject',
  624. 'subsubsubsubject']
  625. if self.document_class in ('book', 'memoir', 'report',
  626. 'scrbook', 'scrreprt'):
  627. self.sections_numbered.insert(0, 'chapter')
  628. if self._with_part:
  629. self.sections_numbered.insert(0, 'part')
  630. def section(self, level):
  631. """Return the LaTeX section name for section `level`.
  632. The name depends on the specific document class.
  633. Level is 1,2,3..., as level 0 is the title.
  634. """
  635. if level <= len(self.sections):
  636. return self.sections[level-1]
  637. else:
  638. return self.sections[-1]
  639. class Table(object):
  640. """Manage a table while traversing.
  641. Maybe change to a mixin defining the visit/departs, but then
  642. class Table internal variables are in the Translator.
  643. Table style might be
  644. :standard: horizontal and vertical lines
  645. :booktabs: only horizontal lines (requires "booktabs" LaTeX package)
  646. :borderless: no borders around table cells
  647. :nolines: alias for borderless
  648. """
  649. def __init__(self,translator,latex_type,table_style):
  650. self._translator = translator
  651. self._latex_type = latex_type
  652. self._table_style = table_style
  653. self._open = 0
  654. # miscellaneous attributes
  655. self._attrs = {}
  656. self._col_width = []
  657. self._rowspan = []
  658. self.stubs = []
  659. self._in_thead = 0
  660. def open(self):
  661. self._open = True
  662. self._col_specs = []
  663. self.caption = []
  664. self._attrs = {}
  665. self._in_head = False # maybe context with search
  666. def close(self):
  667. self._open = False
  668. self._col_specs = None
  669. self.caption = []
  670. self._attrs = {}
  671. self.stubs = []
  672. def is_open(self):
  673. return self._open
  674. def set_table_style(self, table_style):
  675. if not table_style in ('standard','booktabs','borderless','nolines'):
  676. return
  677. self._table_style = table_style
  678. def get_latex_type(self):
  679. if self._latex_type == 'longtable' and not self.caption:
  680. # do not advance the "table" counter (requires "ltcaption" package)
  681. return('longtable*')
  682. return self._latex_type
  683. def set(self,attr,value):
  684. self._attrs[attr] = value
  685. def get(self,attr):
  686. if attr in self._attrs:
  687. return self._attrs[attr]
  688. return None
  689. def get_vertical_bar(self):
  690. if self._table_style == 'standard':
  691. return '|'
  692. return ''
  693. # horizontal lines are drawn below a row,
  694. def get_opening(self):
  695. return '\n'.join([r'\setlength{\DUtablewidth}{\linewidth}',
  696. r'\begin{%s}[c]' % self.get_latex_type()])
  697. def get_closing(self):
  698. closing = []
  699. if self._table_style == 'booktabs':
  700. closing.append(r'\bottomrule')
  701. # elif self._table_style == 'standard':
  702. # closing.append(r'\hline')
  703. closing.append(r'\end{%s}' % self.get_latex_type())
  704. return '\n'.join(closing)
  705. def visit_colspec(self, node):
  706. self._col_specs.append(node)
  707. # "stubs" list is an attribute of the tgroup element:
  708. self.stubs.append(node.attributes.get('stub'))
  709. def get_colspecs(self):
  710. """Return column specification for longtable.
  711. Assumes reST line length being 80 characters.
  712. Table width is hairy.
  713. === ===
  714. ABC DEF
  715. === ===
  716. usually gets to narrow, therefore we add 1 (fiddlefactor).
  717. """
  718. width = 80
  719. total_width = 0.0
  720. # first see if we get too wide.
  721. for node in self._col_specs:
  722. colwidth = float(node['colwidth']+1) / width
  723. total_width += colwidth
  724. self._col_width = []
  725. self._rowspan = []
  726. # donot make it full linewidth
  727. factor = 0.93
  728. if total_width > 1.0:
  729. factor /= total_width
  730. bar = self.get_vertical_bar()
  731. latex_table_spec = ''
  732. for node in self._col_specs:
  733. colwidth = factor * float(node['colwidth']+1) / width
  734. self._col_width.append(colwidth+0.005)
  735. self._rowspan.append(0)
  736. latex_table_spec += '%sp{%.3f\\DUtablewidth}' % (bar, colwidth+0.005)
  737. return latex_table_spec+bar
  738. def get_column_width(self):
  739. """Return columnwidth for current cell (not multicell)."""
  740. return '%.2f\\DUtablewidth' % self._col_width[self._cell_in_row-1]
  741. def get_multicolumn_width(self, start, len_):
  742. """Return sum of columnwidths for multicell."""
  743. mc_width = sum([width
  744. for width in ([self._col_width[start + co - 1]
  745. for co in range (len_)])])
  746. return '%.2f\\DUtablewidth' % mc_width
  747. def get_caption(self):
  748. if not self.caption:
  749. return ''
  750. caption = ''.join(self.caption)
  751. if 1 == self._translator.thead_depth():
  752. return r'\caption{%s}\\' '\n' % caption
  753. return r'\caption[]{%s (... continued)}\\' '\n' % caption
  754. def need_recurse(self):
  755. if self._latex_type == 'longtable':
  756. return 1 == self._translator.thead_depth()
  757. return 0
  758. def visit_thead(self):
  759. self._in_thead += 1
  760. if self._table_style == 'standard':
  761. return ['\\hline\n']
  762. elif self._table_style == 'booktabs':
  763. return ['\\toprule\n']
  764. return []
  765. def depart_thead(self):
  766. a = []
  767. #if self._table_style == 'standard':
  768. # a.append('\\hline\n')
  769. if self._table_style == 'booktabs':
  770. a.append('\\midrule\n')
  771. if self._latex_type == 'longtable':
  772. if 1 == self._translator.thead_depth():
  773. a.append('\\endfirsthead\n')
  774. else:
  775. a.append('\\endhead\n')
  776. a.append(r'\multicolumn{%d}{c}' % len(self._col_specs) +
  777. r'{\hfill ... continued on next page} \\')
  778. a.append('\n\\endfoot\n\\endlastfoot\n')
  779. # for longtable one could add firsthead, foot and lastfoot
  780. self._in_thead -= 1
  781. return a
  782. def visit_row(self):
  783. self._cell_in_row = 0
  784. def depart_row(self):
  785. res = [' \\\\\n']
  786. self._cell_in_row = None # remove cell counter
  787. for i in range(len(self._rowspan)):
  788. if (self._rowspan[i]>0):
  789. self._rowspan[i] -= 1
  790. if self._table_style == 'standard':
  791. rowspans = [i+1 for i in range(len(self._rowspan))
  792. if (self._rowspan[i]<=0)]
  793. if len(rowspans)==len(self._rowspan):
  794. res.append('\\hline\n')
  795. else:
  796. cline = ''
  797. rowspans.reverse()
  798. # TODO merge clines
  799. while 1:
  800. try:
  801. c_start = rowspans.pop()
  802. except:
  803. break
  804. cline += '\\cline{%d-%d}\n' % (c_start,c_start)
  805. res.append(cline)
  806. return res
  807. def set_rowspan(self,cell,value):
  808. try:
  809. self._rowspan[cell] = value
  810. except:
  811. pass
  812. def get_rowspan(self,cell):
  813. try:
  814. return self._rowspan[cell]
  815. except:
  816. return 0
  817. def get_entry_number(self):
  818. return self._cell_in_row
  819. def visit_entry(self):
  820. self._cell_in_row += 1
  821. def is_stub_column(self):
  822. if len(self.stubs) >= self._cell_in_row:
  823. return self.stubs[self._cell_in_row-1]
  824. return False
  825. class LaTeXTranslator(nodes.NodeVisitor):
  826. # When options are given to the documentclass, latex will pass them
  827. # to other packages, as done with babel.
  828. # Dummy settings might be taken from document settings
  829. # Config setting defaults
  830. # -----------------------
  831. # TODO: use mixins for different implementations.
  832. # list environment for docinfo. else tabularx
  833. ## use_optionlist_for_docinfo = False # TODO: NOT YET IN USE
  834. # Use compound enumerations (1.A.1.)
  835. compound_enumerators = 0
  836. # If using compound enumerations, include section information.
  837. section_prefix_for_enumerators = 0
  838. # This is the character that separates the section ("." subsection ...)
  839. # prefix from the regular list enumerator.
  840. section_enumerator_separator = '-'
  841. # Auxiliary variables
  842. # -------------------
  843. has_latex_toc = False # is there a toc in the doc? (needed by minitoc)
  844. is_toc_list = False # is the current bullet_list a ToC?
  845. section_level = 0
  846. # Flags to encode():
  847. # inside citation reference labels underscores dont need to be escaped
  848. inside_citation_reference_label = False
  849. verbatim = False # do not encode
  850. insert_non_breaking_blanks = False # replace blanks by "~"
  851. insert_newline = False # add latex newline commands
  852. literal = False # literal text (block or inline)
  853. def __init__(self, document, babel_class=Babel):
  854. nodes.NodeVisitor.__init__(self, document)
  855. # Reporter
  856. # ~~~~~~~~
  857. self.warn = self.document.reporter.warning
  858. self.error = self.document.reporter.error
  859. # Settings
  860. # ~~~~~~~~
  861. self.settings = settings = document.settings
  862. self.latex_encoding = self.to_latex_encoding(settings.output_encoding)
  863. self.use_latex_toc = settings.use_latex_toc
  864. self.use_latex_docinfo = settings.use_latex_docinfo
  865. self._use_latex_citations = settings.use_latex_citations
  866. self.embed_stylesheet = settings.embed_stylesheet
  867. self._reference_label = settings.reference_label
  868. self.hyperlink_color = settings.hyperlink_color
  869. self.compound_enumerators = settings.compound_enumerators
  870. # self.font_encoding = getattr(settings, 'font_encoding', '')
  871. self.font_encoding = None
  872. self.section_prefix_for_enumerators = (
  873. settings.section_prefix_for_enumerators)
  874. self.section_enumerator_separator = (
  875. settings.section_enumerator_separator.replace('_', r'\_'))
  876. # literal blocks:
  877. self.literal_block_env = ''
  878. self.literal_block_options = ''
  879. if settings.literal_block_env != '':
  880. (none,
  881. self.literal_block_env,
  882. self.literal_block_options,
  883. none ) = re.split('(\w+)(.*)', settings.literal_block_env)
  884. elif settings.use_verbatim_when_possible:
  885. self.literal_block_env = 'verbatim'
  886. #
  887. if self.settings.use_bibtex:
  888. self.bibtex = self.settings.use_bibtex.split(',',1)
  889. # TODO avoid errors on not declared citations.
  890. else:
  891. self.bibtex = None
  892. # language module for Docutils-generated text
  893. # (labels, bibliographic_fields, and author_separators)
  894. self.language_module = languages.get_language(settings.language_code,
  895. document.reporter)
  896. self.babel = babel_class(settings.language_code, document.reporter)
  897. self.author_separator = self.language_module.author_separators[0]
  898. d_options = [self.settings.documentoptions]
  899. if self.babel.language not in ('english', ''):
  900. d_options.append(self.babel.language)
  901. self.documentoptions = ','.join(filter(None, d_options))
  902. self.d_class = DocumentClass(settings.documentclass,
  903. settings.use_part_section)
  904. # graphic package options:
  905. if self.settings.graphicx_option == '':
  906. self.graphicx_package = r'\usepackage{graphicx}'
  907. elif self.settings.graphicx_option.lower() == 'auto':
  908. self.graphicx_package = PreambleCmds.graphicx_auto
  909. else:
  910. self.graphicx_package = (r'\usepackage[%s]{graphicx}' %
  911. self.settings.graphicx_option)
  912. # footnotes:
  913. self.docutils_footnotes = settings.docutils_footnotes
  914. if settings.use_latex_footnotes:
  915. self.docutils_footnotes = True
  916. self.warn('`use_latex_footnotes` is deprecated. '
  917. 'The setting has been renamed to `docutils_footnotes` '
  918. 'and the alias will be removed in a future version.')
  919. self.figure_footnotes = settings.figure_footnotes
  920. if self.figure_footnotes:
  921. self.docutils_footnotes = True
  922. self.warn('The "figure footnotes" workaround/setting is strongly '
  923. 'deprecated and will be removed in a future version.')
  924. # Output collection stacks
  925. # ~~~~~~~~~~~~~~~~~~~~~~~~
  926. # Document parts
  927. #self.head_prefix = [r'\documentclass[%s]{%s}' %
  928. # (self.documentoptions, self.settings.documentclass)]
  929. self.head_prefix = []
  930. self.requirements = SortableDict() # made a list in depart_document()
  931. # self.requirements['__static'] = r'\usepackage{ifthen}'
  932. self.latex_preamble = []
  933. self.context_preamble = [settings.context_preamble]
  934. self.stylesheet = []
  935. self.fallbacks = SortableDict() # made a list in depart_document()
  936. self.pdfsetup = [] # PDF properties (hyperref package)
  937. self.title = []
  938. self.subtitle = []
  939. self.titledata = [] # \title, \author, \date
  940. ## self.body_prefix = ['\\begin{document}\n']
  941. self.body_pre_docinfo = [] # \maketitle
  942. self.docinfo = []
  943. self.dedication = []
  944. self.abstract = []
  945. self.body = []
  946. ## self.body_suffix = ['\\end{document}\n']
  947. # A heterogenous stack used in conjunction with the tree traversal.
  948. # Make sure that the pops correspond to the pushes:
  949. self.context = []
  950. # Title metadata:
  951. self.title_labels = []
  952. self.subtitle_labels = []
  953. # (if use_latex_docinfo: collects lists of
  954. # author/organization/contact/address lines)
  955. self.author_stack = []
  956. self.date = []
  957. # PDF properties: pdftitle, pdfauthor
  958. # TODO?: pdfcreator, pdfproducer, pdfsubject, pdfkeywords
  959. self.pdfinfo = []
  960. self.pdfauthor = []
  961. # Stack of section counters so that we don't have to use_latex_toc.
  962. # This will grow and shrink as processing occurs.
  963. # Initialized for potential first-level sections.
  964. self._section_number = [0]
  965. # The current stack of enumerations so that we can expand
  966. # them into a compound enumeration.
  967. self._enumeration_counters = []
  968. # The maximum number of enumeration counters we've used.
  969. # If we go beyond this number, we need to create a new
  970. # counter; otherwise, just reuse an old one.
  971. self._max_enumeration_counters = 0
  972. self._bibitems = []
  973. # object for a table while proccessing.
  974. self.table_stack = []
  975. self.active_table = Table(self, 'longtable', settings.table_style)
  976. # Where to collect the output of visitor methods (default: body)
  977. self.out = self.body
  978. self.out_stack = [] # stack of output collectors
  979. # Process settings
  980. # ~~~~~~~~~~~~~~~~
  981. # Encodings:
  982. # Docutils' output-encoding => TeX input encoding
  983. #if self.latex_encoding != 'ascii':
  984. # self.requirements['_inputenc'] = (r'\usepackage[%s]{inputenc}'
  985. # % self.latex_encoding)
  986. # TeX font encoding
  987. #if self.font_encoding:
  988. # self.requirements['_fontenc'] = (r'\usepackage[%s]{fontenc}' %
  989. # self.font_encoding)
  990. # page layout with typearea (if there are relevant document options)
  991. if (settings.documentclass.find('scr') == -1 and
  992. (self.documentoptions.find('DIV') != -1 or
  993. self.documentoptions.find('BCOR') != -1)):
  994. self.requirements['typearea'] = r'\usepackage{typearea}'
  995. # Stylesheets
  996. # get list of style sheets from settings
  997. styles = utils.get_stylesheet_list(settings)
  998. # adapt path if --stylesheet_path is used
  999. if settings.stylesheet_path and not(self.embed_stylesheet):
  1000. styles = [utils.relative_path(settings._destination, sheet)
  1001. for sheet in styles]
  1002. for sheet in styles:
  1003. (base, ext) = os.path.splitext(sheet)
  1004. is_package = ext in ['.sty', '']
  1005. if self.embed_stylesheet:
  1006. if is_package:
  1007. sheet = base + '.sty' # adapt package name
  1008. # wrap in \makeatletter, \makeatother
  1009. wrapper = PreambleCmds.embedded_package_wrapper
  1010. else:
  1011. wrapper = '%% embedded stylesheet: %s\n%s'
  1012. settings.record_dependencies.add(sheet)
  1013. self.stylesheet.append(wrapper %
  1014. (sheet, io.FileInput(source_path=sheet, encoding='utf-8').read()))
  1015. else: # link to style sheet
  1016. if is_package:
  1017. self.stylesheet.append(r'\usepackage{%s}' % base)
  1018. else:
  1019. self.stylesheet.append(r'\input{%s}' % sheet)
  1020. # PDF setup
  1021. if self.hyperlink_color in ('0', 'false', 'False', ''):
  1022. self.hyperref_options = ''
  1023. else:
  1024. self.hyperref_options = 'colorlinks=true,linkcolor=%s,urlcolor=%s' % (
  1025. self.hyperlink_color, self.hyperlink_color)
  1026. if settings.hyperref_options:
  1027. self.hyperref_options += ',' + settings.hyperref_options
  1028. # LaTeX Toc
  1029. # include all supported sections in toc and PDF bookmarks
  1030. # (or use documentclass-default (as currently))?
  1031. ## if self.use_latex_toc:
  1032. ## self.requirements['tocdepth'] = (r'\setcounter{tocdepth}{%d}' %
  1033. ## len(self.d_class.sections))
  1034. # LaTeX section numbering
  1035. if not self.settings.sectnum_xform: # section numbering by LaTeX:
  1036. # sectnum_depth:
  1037. # None "sectnum" directive without depth arg -> LaTeX default
  1038. # 0 no "sectnum" directive -> no section numbers
  1039. # else value of the "depth" argument: translate to LaTeX level
  1040. # -1 part (0 with "article" document class)
  1041. # 0 chapter (missing in "article" document class)
  1042. # 1 section
  1043. # 2 subsection
  1044. # 3 subsubsection
  1045. # 4 paragraph
  1046. # 5 subparagraph
  1047. if settings.sectnum_depth is not None:
  1048. # limit to supported levels
  1049. sectnum_depth = min(settings.sectnum_depth,
  1050. len(self.d_class.sections))
  1051. # adjust to document class and use_part_section settings
  1052. if 'chapter' in self.d_class.sections:
  1053. sectnum_depth -= 1
  1054. if self.d_class.sections[0] == 'part':
  1055. sectnum_depth -= 1
  1056. self.requirements['sectnum_depth'] = (
  1057. r'\setcounter{secnumdepth}{%d}' % sectnum_depth)
  1058. # start with specified number:
  1059. if (hasattr(settings, 'sectnum_start') and
  1060. settings.sectnum_start != 1):
  1061. self.requirements['sectnum_start'] = (
  1062. r'\setcounter{%s}{%d}' % (self.d_class.sections[0],
  1063. settings.sectnum_start-1))
  1064. # currently ignored (configure in a stylesheet):
  1065. ## settings.sectnum_prefix
  1066. ## settings.sectnum_suffix
  1067. # Auxiliary Methods
  1068. # -----------------
  1069. def to_latex_encoding(self,docutils_encoding):
  1070. """Translate docutils encoding name into LaTeX's.
  1071. Default method is remove "-" and "_" chars from docutils_encoding.
  1072. """
  1073. tr = { 'iso-8859-1': 'latin1', # west european
  1074. 'iso-8859-2': 'latin2', # east european
  1075. 'iso-8859-3': 'latin3', # esperanto, maltese
  1076. 'iso-8859-4': 'latin4', # north european, scandinavian, baltic
  1077. 'iso-8859-5': 'iso88595', # cyrillic (ISO)
  1078. 'iso-8859-9': 'latin5', # turkish
  1079. 'iso-8859-15': 'latin9', # latin9, update to latin1.
  1080. 'mac_cyrillic': 'maccyr', # cyrillic (on Mac)
  1081. 'windows-1251': 'cp1251', # cyrillic (on Windows)
  1082. 'koi8-r': 'koi8-r', # cyrillic (Russian)
  1083. 'koi8-u': 'koi8-u', # cyrillic (Ukrainian)
  1084. 'windows-1250': 'cp1250', #
  1085. 'windows-1252': 'cp1252', #
  1086. 'us-ascii': 'ascii', # ASCII (US)
  1087. # unmatched encodings
  1088. #'': 'applemac',
  1089. #'': 'ansinew', # windows 3.1 ansi
  1090. #'': 'ascii', # ASCII encoding for the range 32--127.
  1091. #'': 'cp437', # dos latin us
  1092. #'': 'cp850', # dos latin 1
  1093. #'': 'cp852', # dos latin 2
  1094. #'': 'decmulti',
  1095. #'': 'latin10',
  1096. #'iso-8859-6': '' # arabic
  1097. #'iso-8859-7': '' # greek
  1098. #'iso-8859-8': '' # hebrew
  1099. #'iso-8859-10': '' # latin6, more complete iso-8859-4
  1100. }
  1101. encoding = docutils_encoding.lower()
  1102. if encoding in tr:
  1103. return tr[encoding]
  1104. # convert: latin-1, latin_1, utf-8 and similar things
  1105. encoding = encoding.replace('_', '').replace('-', '')
  1106. # strip the error handler
  1107. return encoding.split(':')[0]
  1108. def language_label(self, docutil_label):
  1109. return self.language_module.labels[docutil_label]
  1110. def ensure_math(self, text):
  1111. if not hasattr(self, 'ensure_math_re'):
  1112. chars = { # lnot,pm,twosuperior,threesuperior,mu,onesuperior,times,div
  1113. 'latin1' : '\xac\xb1\xb2\xb3\xb5\xb9\xd7\xf7' , # ¬±²³µ¹×÷
  1114. # TODO?: use texcomp instead.
  1115. }
  1116. self.ensure_math_re = re.compile('([%s])' % chars['latin1'])
  1117. text = self.ensure_math_re.sub(r'\\ensuremath{\1}', text)
  1118. return text
  1119. def encode(self, text):
  1120. """Return text with 'problematic' characters escaped.
  1121. Escape the ten special printing characters ``# $ % & ~ _ ^ \ { }``,
  1122. square brackets ``[ ]``, double quotes and (in OT1) ``< | >``.
  1123. Separate ``-`` (and more in literal text) to prevent input ligatures.
  1124. Translate non-supported Unicode characters.
  1125. """
  1126. if self.verbatim:
  1127. return text
  1128. # Separate compound characters, e.g. '--' to '-{}-'.
  1129. separate_chars = '-'
  1130. # In monospace-font, we also separate ',,', '``' and "''" and some
  1131. # other characters which can't occur in non-literal text.
  1132. if self.literal:
  1133. separate_chars += ',`\'"<>'
  1134. # LaTeX encoding maps:
  1135. special_chars = {
  1136. ord('#'): ur'\#',
  1137. ord('$'): ur'\$',
  1138. ord('%'): ur'\%',
  1139. ord('&'): ur'\&',
  1140. ord('~'): ur'\textasciitilde{}',
  1141. ord('_'): ur'\_',
  1142. ord('^'): ur'\textasciicircum{}',
  1143. ord('\\'): ur'\textbackslash{}',
  1144. ord(…

Large files files are truncated, but you can click here to view the full file