#!/usr/bin/env python # -*- coding: utf8 -*- # :Copyright: © 2011 Günter Milde. # :Licence: This work may be distributed and/or modified under the # conditions of the `LaTeX Project Public License`_, # either version 1.3 of this license or (at your option) # any later version. # :Id: $Id: $ # # .. _LaTeX Project Public License: http://www.latex-project.org/lppl.txt # Released without warranties or conditions of any kind # # :: """Unicode characters and corresponding LaTeX math mode commands""" # This script generates a LaTeX source file for compilation with the # XeTeX engine. It also provides functions for other XeTeX generating # scripts:: import sys import parse_unimathsymbols # Configuration # ------------- # I/O outfile = file('../unimathsymbols.tex', 'w') # outfile = sys.stdout # Include entries for characters without (listed) LaTeX macro? # :: include_unsupported_chars = True # include_unsupported_chars = False # Include macros from the following packages:: packages = ['', 'literal', # "feature", no real packge 'amssymb', 'amsmath', 'amsxtra', 'bbold', # 'esint', # 'fourier', # 'gensymb', 'isomath', # 'kmath', # 'lxfonts', # 'mathabx', # 'mathcomp', # 'mathdesign' 'mathdots', # 'MnSymbol' # 'omlmathit', # 'pzccal', # 'txfonts', 'stmaryrd', 'wasysym', # 'wrisym', ] # Some packages require options or configuration code for proper working # (at least with XeLaTeX and xunicode):: package_options = {'isomath': '[rmdefault=cmr]', 'mathdesign': '[charter]', 'kpfonts': '[nomathscript]', 'mathbbol': '[cspex]', } package_config = {'oz': r' \let\TH\relax'} # Implementation # --------------- # Some requirements are not real packages but features [1]_ # # .. [1] A feature can be a set of commands common to several packages, # (e.g. ``bbold`` or ``slantedGreek``) or a constraint of the mapping # (e.g. ``literal``, mapping plain characters to upright face). # # :: features = ['', 'literal', 'mathbb', 'slantedGreek', 'isostyle', 'frenchstyle', 'uprightstyle', ] def package_calls(packages): pkg_calls = [r'\usepackage%s{%s}%s' % (package_options.get(pkg, ''), pkg, package_config.get(pkg, '')) for pkg in packages # filter "standard" and "features" (virtual packages) if pkg not in features] return '\n'.join(pkg_calls) # macro replacements for active LaTeX characters:: def txt2tex(s): # TeX special_chars table = { ord('#'): ur'\#', ord('$'): ur'\$', ord('%'): ur'\%', ord('&'): ur'\&', ord('~'): ur'\textasciitilde{}', ord('_'): ur'\_', ord('^'): ur'\textasciicircum{}', ord('\\'): ur'\textbackslash{}', ord('{'): ur'\{', ord('}'): ur'\}', } # Font substitutions for characters that are not defined in XITS # monospaced: for i in range(0x2336, 0x237A) + [0xFB29]: table[i] = ur'\texttt %c' % i # sans: for i in ( [0x2007, 0x200B, 0x200C, 0x02610, 0x02611] + range(0x207A, 0x208F) + range(0x263C, 0x2654) + range(0x2B00, 0x2B12) # + range(0x3008, 0x301C) not in DejaVu Sans ): table[i] = ur'\textsf %c' % i return s.decode('utf-8').translate(table).encode('utf-8') # math mode macro example: def macro_example(entry, packages, wrap_spaces=True): """Return a math macro that works with the currently selected packages, a substitution (in parentheses) or [na] """ cmd = entry.supported_cmd(packages) wrapper = '$%s$' if not cmd: cmd = entry.substitution_cmd(packages) wrapper = '$(%s)$' if cmd: # add a base character to accent and radical macros: if entry.category in ('mathaccent', 'mathradical', 'mathover', 'mathunder'): cmd += '{x}' # wrap spaces in a colorbox to make them visible: if wrap_spaces and entry.math_class == 'S': cmd = r'\spacebox{%s}' % cmd # commands requiring \left \right if cmd == r'\lgroup': cmd = r'\left\lgroup\right.' if cmd == r'\rgroup': cmd = r'\left.\right\rgroup' return wrapper % cmd if entry.cmd: # not available with current package selection return '[na]' return '' preamble = r"""\documentclass[a4paper,landscape]{article} \usepackage{fixltx2e} \usepackage{longtable,booktabs} \usepackage[tmargin=2cm,bmargin=2cm,lmargin=2cm,rmargin=2cm]{geometry} \setlength{\parindent}{0em} \usepackage{xcolor} \setlength{\fboxsep}{0em} %% also for colorbox sep \newcommand{\spacebox}[1]{\colorbox{lightgray}{\rule{0pt}{1em}$#1$}} %% Requirements %s %% Text font \usepackage[no-math]{fontspec} \usepackage{xunicode} \setmainfont[BoldFont={XITS Bold},ItalicFont={XITS Italic}]{XITS Math} \setsansfont{DejaVu Sans} \setmonofont[HyphenChar=None,Scale=MatchUppercase]{DejaVu Sans Mono} %% \setmonofont[HyphenChar=None,Scale=MatchUppercase]{FreeMono} \begin{document} \section*{%s} """ used_features = r""" Active features: \texttt{%s}. """ used_packages = r""" Used packages: \texttt{%s}. Due to (8-bit) TeX's limitation to 16 math alphabets and conflicts between some packages, not all symbols can accessed simultaneously. [\emph{na}] in the math symbol column indicates that the symbol is not available with the currently selected packages. """ table_head = r""" \begin{longtable}{lccllp{2.7cm}p{12.5cm}} \toprule No. & Text & Math & Macro & Category & Requirements & Comments\\ \midrule \endhead """ table_foot = r""" \bottomrule \end{longtable} """ if __name__ == '__main__': outfile.write(preamble % (package_calls(packages), __doc__)) outfile.write(used_features % ', '.join([pkg for pkg in packages if pkg and pkg in features])) outfile.write(used_packages % ', '.join([pkg for pkg in packages if pkg not in features])) outfile.write(table_head) # table lines for (key, entry) in parse_unimathsymbols.read_data(): cmd = macro_example(entry, packages) if not cmd: if not include_unsupported_chars: continue utf8 = txt2tex(entry.utf8) if entry.math_class == 'S': utf8 = r'\spacebox{%s}' % utf8 line = ' & '.join(['%05X' % entry.codepoint, utf8, cmd, txt2tex(entry.cmd), entry.category, entry.requirements, txt2tex(entry.comment), ]) + r' \\' outfile.write(line + '\n') # the end outfile.write(table_foot) outfile.write(r'\end{document}') if outfile != sys.stdout: print "Output written to", outfile.name