Last active
November 10, 2022 00:04
-
-
Save jlumpe/dabd62e3f209633eea60da205af0dd45 to your computer and use it in GitHub Desktop.
My set of custom LaTeX macros
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# Create and install tex package for macros | |
set -ex | |
TEXMFHOME=`kpsewhich -var-value=TEXMFHOME` | |
dir="$TEXMFHOME/tex/latex/custom" | |
mkdir -p "$dir" | |
./mathmacros.py sty > "$dir/mymath.sty" | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
"""Defines the macros, and outputs in one of several formats.""" | |
import sys | |
import os | |
# Format is "commandname": ("value", numargs) | |
MACROS = { | |
# Vector and matrix variables | |
'Vect': (r'\boldsymbol{#1}', 1), | |
'Mat': (r'\boldsymbol{#1}', 1), | |
# Specific symbols as vectors/matrices | |
'Vectmu': (r'\Vect{\mu}', 0), | |
'Vectx': (r'\Vect{x}', 0), | |
'Vecty': (r'\Vect{y}', 0), | |
'Vectu': (r'\Vect{u}', 0), | |
'Vectv': (r'\Vect{v}', 0), | |
'MatSigma': (r'\Mat{\Sigma}', 0), | |
# Number sets | |
'Reals': (r'\mathbb{R}', 0), | |
'Complexes': (r'\mathbb{C}', 0), | |
'Rationals': (r'\mathbb{Q}', 0), | |
'Integers': (r'\mathbb{Z}', 0), | |
'Naturals': (r'\mathbb{N}', 0), | |
'Vectors': (r'\Reals^{#1}', 1), | |
'Matrices': (r'\Reals^{#1 \times #2}', 2), | |
# Partial derivatives | |
'Partial': (r'\frac{\partial #1}{\partial #2}', 2), | |
'Partiall': (r'\frac{\partial #1^2}{\partial #2 \partial #3}', 3), | |
'Partialll': (r'\frac{\partial #1^3}{\partial #2 \partial #3 \partial #4}', 4), | |
# KL divergence | |
'DKL': (r'D_\text{KL}(#1 \parallel #2)', 2), | |
# Quadratic form, like x^T A x | |
'Quadform': (r'#1^T #2 #1', 2), | |
'Quadformt': (r'#1 #2 #1^T', 2), | |
} | |
REQUIRED_PACKAGES = ['amsmath', 'amsfonts', 'mathtools'] | |
# Raw tex to append | |
TEX = r""" | |
% Absolute value and magnitude | |
% https://tex.stackexchange.com/questions/43008/absolute-value-symbols | |
\DeclarePairedDelimiter\abs{\lvert}{\rvert}% | |
\DeclarePairedDelimiter\norm{\lVert}{\rVert}% | |
% Swap the definition of \abs* and \norm*, so that \abs | |
% and \norm resizes the size of the brackets, and the | |
% starred version does not. | |
\makeatletter | |
\let\oldabs\abs | |
\def\abs{\@ifstar{\oldabs}{\oldabs*}} | |
% | |
\let\oldnorm\norm | |
\def\norm{\@ifstar{\oldnorm}{\oldnorm*}} | |
\makeatother | |
""" | |
# Test usage for macros | |
MACRO_EXAMPLES = { | |
macro: ['\\' + macro] if nargs == 0 else [] | |
for macro, (_, nargs) in MACROS.items() | |
} | |
MACRO_EXAMPLES['Vect'] = [r'\Vect{x}'] | |
MACRO_EXAMPLES['Mat'] = [r'\Mat{X}'] | |
MACRO_EXAMPLES['Vectors'] = [r'\Vectors{n}'] | |
MACRO_EXAMPLES['Matrices'] = [r'\Matrices{n}{m}'] | |
MACRO_EXAMPLES['Partial'] = [ | |
r'\Partial{f}{x}', | |
r'\Partial{}{x} f(x)', | |
] | |
MACRO_EXAMPLES['Partiall'] = [ | |
r'\Partiall{f}{x}{y}', | |
r'\Partiall{}{x}{y} f(x, y)' | |
] | |
MACRO_EXAMPLES['Partialll'] = [ | |
r'\Partialll{f}{x}{y}{z}', | |
r'\Partialll{}{x}{y}{z} f(x, y, z)', | |
] | |
MACRO_EXAMPLES['DKL'] = [r'\DKL{x}{y}'] | |
MACRO_EXAMPLES['Quadform'] = [r'\Quadform{\Vect{x}}{\Mat{A}}'] | |
MACRO_EXAMPLES['Quadformt'] = [r'\Quadformt{\Vect{x}}{\Mat{A}}'] | |
MACRO_EXAMPLES['abs'] = [ | |
r'\abs{x}', | |
r'\abs{\frac{x}{y}}', | |
r'\abs*{\frac{x}{y}}', | |
] | |
MACRO_EXAMPLES['norm'] = [ | |
r'\norm{\Vect{u}}', | |
r'\norm{\frac{1}{2}\Vect{u} + \frac{1}{2}\Vect{v}}', | |
r'\norm*{\frac{1}{2}\Vect{u} + \frac{1}{2}\Vect{v}}', | |
] | |
def newcommand(name, command, nargs=0): | |
if nargs > 0: | |
return r'\newcommand{\%s}[%d]{%s}' % (name, nargs, command) | |
else: | |
return r'\newcommand{\%s}{%s}' % (name, command) | |
def print_tex(): | |
for name, (command, nargs) in MACROS.items(): | |
print(newcommand(name, command, nargs)) | |
print('\n\n') | |
print(TEX) | |
def print_mathjax(): | |
import json | |
print('{') | |
for i, (name, (command, nargs)) in enumerate(MACROS.items()): | |
namejson = json.dumps(name) | |
cmdjson = json.dumps(command) | |
end = ',\n' if i < len(MACROS) - 1 else '\n' | |
if nargs > 0: | |
print('\t%s: [%s, %d]' % (namejson, cmdjson, nargs), end=end) | |
else: | |
print('\t%s: %s' % (namejson, cmdjson), end=end) | |
print('}') | |
def print_sty(): | |
for package in REQUIRED_PACKAGES: | |
print(r'\RequirePackage{%s}' % package) | |
print() | |
print_tex() | |
def _print_macros_table(vspace='1ex', vstretch=None, borders=False, align='l'): | |
max_examples = max(map(len, MACRO_EXAMPLES.values())) | |
nextrow = r'\\[%s]' % vspace if vspace else r'\\' | |
if borders: | |
nextrow += ' \\hline' | |
if vstretch is not None: | |
print('\\renewcommand{\\vstretch}{%s}\n' % vstretch) | |
v = '|' if borders else '' | |
cols_arg = v + 'l' + v + (align * max_examples) + v | |
print(r'\begin{longtable}{ %s }' % cols_arg) | |
if borders: | |
print('\\hline') | |
for macro, examples in MACRO_EXAMPLES.items(): | |
print('\\verb+\\', macro, '+ ', sep='', end='') | |
for i, example in enumerate(examples): | |
print('& $\\displaystyle', example, '$ ', end='') | |
print(nextrow) | |
print(r'\end{longtable}') | |
def print_example(pkgname='mymath'): | |
packages = [pkgname, 'longtable', *REQUIRED_PACKAGES] | |
# Preamble | |
print(r'\documentclass{article}') | |
print() | |
for package in packages: | |
print(r'\RequirePackage{%s}' % package) | |
print('\n\\begin{document}') | |
# Macros table | |
print('\n\\section{Macros}') | |
print() | |
_print_macros_table() | |
# Other stuff | |
#print('\n\\section{Other}') | |
print('\n\\end{document}') | |
PRINTERS = { | |
'tex': (print_tex, 'Plain TEX file with macro definitions.'), | |
'mathjax': (print_mathjax, 'MathJax JSON.'), | |
'sty': (print_sty, '.sty file with required package imports and macro definitions.'), | |
'example': (print_example, 'TEX file with example usage of all defined commands.'), | |
} | |
def print_usage(): | |
print('Usage: %s FORMAT' % os.path.basename(sys.argv[0])) | |
print() | |
print('Available formats:') | |
for fmt, (f, desc) in PRINTERS.items(): | |
print('\t{}: {}'.format(fmt, desc)) | |
if __name__ == '__main__': | |
if len(sys.argv) != 2: | |
print_usage() | |
sys.exit(1) | |
fmt = sys.argv[1].lower() | |
if fmt not in PRINTERS: | |
print_usage() | |
sys.exit(1) | |
f, desc = PRINTERS[fmt] | |
f() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment