Skip to content

Instantly share code, notes, and snippets.

@goerz
Created March 24, 2022 03:05
Show Gist options
  • Save goerz/bdb599011e4a9c8e7ae59de5c54cb065 to your computer and use it in GitHub Desktop.
Save goerz/bdb599011e4a9c8e7ae59de5c54cb065 to your computer and use it in GitHub Desktop.
Python script for extracting textblocks from Beamer presentations
#!/usr/bin/env python
"""Extract textblocks from a Beamer presentation.
This is useful for making Powerpoint slides from Beamer presentations.
"""
import logging
import click
from pathlib import Path
PREAMBLE = r"""\documentclass[compress, aspectratio=169]{beamer}
\usepackage[utf8]{inputenc}
\usepackage{braket}
\newcommand{\identity}[0]{\mathbf{1}}
\newcommand{\Op}[1]{\ensuremath{\mathsf{\hat{#1}}}}
\newcommand{\Abs}[1]{\left|#1\right|}
\newcommand{\AbsSq}[1]{\left|#1\right|^2}
\newcommand{\Norm}[1]{\left\lVert#1\right\rVert}
\newcommand{\NormSq}[1]{\Norm{#1}^2}
\newcommand{\tr}{\mathrm{tr}}
\newcommand{\Tr}{\mathrm{tr}}
\newcommand{\SU}{\ensuremath{\text{SU}}}
\newcommand{\ketbra}[2]{\ket{#1}\!\bra{#2}}
\newcommand{\mirror}{\text{mirror}}
\newcommand{\tgt}{\text{tgt}}
\newcommand{\pop}{\operatorname{pop}}
\newcommand{\dd}{\mathrm{d}}
\newcommand{\ii}{\mathrm{i}}
\newcommand{\Integers}{\mathbb{Z}}
\renewcommand{\Re}{\mathrm{Re}}
\renewcommand{\Im}{\mathrm{Im}}
\newcommand{\partdifquo}[2][{}]{\frac{\partial #1}{\partial #2}}
\newcommand{\Complex}{\mathbb{C}}
\usepackage{textcomp} % provides \textmu
\usepackage{tikz,pgflibraryshapes}
\usepackage{hyperref}
\usepackage{fontawesome}
\usetikzlibrary{arrows.meta, calc, decorations.pathmorphing, backgrounds, positioning}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Grid %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Set up grid for absolute text positioning (page size = 16 x 9 cm)
\usepackage[absolute, overlay]{textpos} % (add `showboxes` for debugging)
%\usepackage[absolute, overlay, showboxes]{textpos} % (add `showboxes` for debugging)
\textblockorigin{0cm}{0cm} % The grid guides start from top left
\setlength{\TPHorizModule}{1cm} % Units are 1 cm ...
\setlength{\TPVertModule}{1cm} % ... and y coordinates point down
% Now you can use e.g.:
% \begin{textblock}{3}(4,2)
% \dots
% \end{textblock}
% to place a block 3cm wide, 4cm right and 2cm up from the bottom left corner
%%%%%%%%%%%%%%%%%%%%%%%%%%% Theme Settings %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\definecolor{DarkBlue}{rgb}{0.1,0.1,0.5}
\definecolor{DarkRed}{rgb}{0.75,0.,0.}
\definecolor{Magenta}{rgb}{1.0,0.0,1.0}
\definecolor{Red}{rgb}{0.894,0.102,0.110}
\definecolor{Green}{rgb}{0.302,0.686,0.290}
\definecolor{Blue}{rgb}{0.216,0.494,0.722}
\definecolor{Orange}{rgb}{1.000,0.498,0.000}
\definecolor{Yellow}{rgb}{0.824,0.824,0.082}
\definecolor{Brown}{rgb}{0.651,0.337,0.157}
\definecolor{LightBlue}{rgb}{0.651,0.808,0.890}
\definecolor{Purple}{rgb}{0.596,0.306,0.639}
\definecolor{LightPurple}{rgb}{0.792,0.698,0.839}
\definecolor{Grey}{rgb}{0.600,0.600,0.600}
\definecolor{LightGreen}{rgb}{0.698,0.875,0.541}
\definecolor{LightOrange}{rgb}{0.992,0.749,0.435}
\definecolor{Pink}{rgb}{0.969,0.506,0.749}
\definecolor{Black}{rgb}{0.000,0.000,0.000}
\definecolor{LightRed}{rgb}{0.984,0.604,0.600}
\definecolor{White}{rgb}{1.000,1.000,1.000}
\definecolor{ARLGray25}{rgb}{0.698,0.698,0.698}
%%%%%%%%%%%%%%%%%%%%%%%%%%% Theme Settings %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\usetheme{Berlin}
\useoutertheme{shadow}
\useinnertheme{default}
\setbeamercolor{palette primary}{use=structure,fg=black,bg=black!20!white}
\setbeamercolor{palette secondary}{use=structure,fg=black,bg=black!25!white}
\setbeamercolor{palette tertiary}{use=structure,fg=black,bg=black!30!white}
\setbeamercolor{palette quaternary}{use=structure,fg=black,bg=black!35!white}
\setbeamercolor{sidebar}{use=structure,bg=structure.fg!20!white}
\setbeamercolor{palette sidebar primary}{use=normal text,fg=normal text.fg}
\setbeamercolor{palette sidebar secondary}{use=structure,fg=structure.fg}
\setbeamercolor{palette sidebar tertiary}{use=normal text,fg=normal text.fg}
\setbeamercolor{palette sidebar quaternary}{use=structure,fg=structure.fg}
\setbeamercolor*{titlelike}{parent=palette primary}
\setbeamercolor*{separation line}{}
\setbeamercolor*{fine separation line}{}
\setbeamertemplate{blocks}[rounded][shadow=false]
\setbeamerfont{title}{family*=phv, size*={20}{24}}
\setbeamerfont{author}{family*=phv, size*={12}{14}}
\setbeamerfont{institute}{family*=phv, size*={8.0}{12}}
\setbeamerfont{date}{family*=phv, size*={8.0}{12}}
\setbeamerfont{classification}{family*=phv, size*={3.78}{4.5}}
\setbeamerfont{frametitle}{series=\bfseries, family*=phv, size*={11.34}{14}}
\defbeamertemplate*{title page}{customized}[1][]{}
\setbeamertemplate{background canvas}{}
\setbeamertemplate{headline}{}
\setbeamertemplate{footline}{}
\setbeamertemplate{frametitle}{}
\usefonttheme[onlysmall]{structurebold}
\setbeamertemplate{bibliography item}{%
\lower2pt\hbox{\pgfuseimage{beamericonarticle}}\insertbiblabel}
\mode<presentation>{\beamertemplatenavigationsymbolsempty}
%\setbeamercolor{block title}{use=structure,fg=white,bg=red!75!black}
%\setbeamercolor{block body}{use=structure,fg=black,bg=red!20!white}
\newcommand{\subhead}[1]{{\bf \color{DarkBlue} #1}}
\newcommand{\mycircledTerm}[1]{\raisebox{-0.6ex}{\textcircled{\scriptsize #1}}}
\newcommand{\mycircled}[1]{\textcircled{\scriptsize #1}}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\begin{document}
"""
POSTAMPLE = r"""
\end{document}
"""
@click.command()
@click.help_option('--help', '-h')
@click.option('--debug', is_flag=True,
help='enable debug logging')
@click.argument("infile", type=click.File('r'))
@click.argument("outfile", type=click.File('w'))
def main(debug, infile, outfile):
"""Extract textblocks"""
logging.basicConfig(level=logging.WARNING)
logger = logging.getLogger(__name__)
if debug:
logger.setLevel(logging.DEBUG)
logger.debug("Enabled debug output")
outfile.write(PREAMBLE)
in_textblock = False
for line in infile:
if line.strip().startswith(r"\begin{textblock}"):
outfile.write(r"\begin{frame}"+"\n")
in_textblock = True
if line.strip().startswith(r"\end{textblock}"):
outfile.write(line)
outfile.write(r"\end{frame}"+"\n\n\n")
in_textblock = False
if in_textblock:
outfile.write(line)
outfile.write(POSTAMPLE)
click.echo(f"Written to {outfile.name}", err=True)
click.echo(f"You can compile with with (pdf)latex", err=True)
pdffile = Path(outfile.name).with_suffix(".pdf")
click.echo(f"You may split the resulting pdf into pages with e.g. `pdfseparate {pdffile} blocks/%03d.pdf`", err=True)
click.echo(f"You can then crop each page with `pdfcrop`", err=True)
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment