I find myself using \begin{frame}[t]\end{frame} all the time. All my attempts to create a macro for it have failed. Is there a way?
2 Answers
If you are not into the underlying LaTeX mechanics and would like to seek for a simplistic way, you can just save your command into a file (e.g. cmd.tex) and declare a macro to \input it.
cmd.tex
\begin{frame}[t]\end{frame}
main document
\documentclass{beamer}
\begin{document}
\newcommand{\newframe}{\input{cmd.tex}}
\newframe
\newframe
\newframe
\newframe
\end{document}
Edit: making use of files
As other answers have pointed out, there is no easy way of defining a macro as \end{frame}\begin{frame}[t], because of LaTeX's parsing mechanism. The (only) way to escape from this dilemma is to make use of files, as I have pointed out before. To support what you want, we can design a (crazy) workaround:
- Save your TeX source code to
file1. - Suppose the macro your designed is
\framesep. We readfile1line by line and replace\framesepto\end{frame}\begin{frame}[t]. The result is saved asfile2. - Read
file2.
The code is shown as below.
\documentclass{beamer}
\usepackage[T1]{fontenc}
\usepackage{expl3}
\usepackage{xparse}
\usepackage{fancyvrb}
\usepackage{datetime2}
\begin{document}
\begin{VerbatimOut}{\jobname.myverb1}
\begin{frame}[t]
frame1
\framesep
frame2
\framesep
frame3
\end{frame}
\end{VerbatimOut}
\ExplSyntaxOn
% replace this regex...
\str_new:N \l_framesep_str
\str_set:Nn \l_framesep_str {\framesep}
% to...
\str_new:N \l_framecmd_str
\str_set:Nn \l_framecmd_str {\end{frame}\begin{frame}[t]}
\ior_new:N \l_infile_ior
\ior_open:Nn \l_infile_ior {\jobname.myverb1}
\iow_new:N \l_outfile_iow
\iow_open:Nn \l_outfile_iow {\jobname.myverb2}
\cs_generate_variant:Nn \regex_replace_all:nnN {ooN}
\ior_str_map_variable:NNn \l_infile_ior \l_tmpa_str {
\regex_replace_all:ooN {\l_framesep_str} {\l_framecmd_str} \l_tmpa_str
\iow_now:Nx \l_outfile_iow {\l_tmpa_str}
}
\ior_close:N \l_infile_ior
\iow_close:N \l_outfile_iow
\ExplSyntaxOff
\input{\jobname.myverb2}
\end{document}
Note that this can also be done by calling a pre-processor before compiling your TeX source. For example, you can have a Python script doing the replacement first and then calling latex.
- 5,227
-
Thank you! It works fine. Now, I try \end{frame}\begin{frame}[t] ad it does not work! I get ! Extra }, or forgotten \endgroup. \endframe ->\egroup \begingroup \def @currenvir {frame} l.1 \end{frame} \begin{frame}[t] Thank you again! latexatha – – latexatha Jul 30 '20 at 18:46
If your aim is to substitute the combination
\end{frame}
\begin{frame}[t]
with, say
\breakframe
then the answer is no, you can't.
As beamer is implememented, it needs to absorb the complete frame code before processing it for making overlays and all other things. So LaTeX needs to see an explicit \end{frame} not buried into a macro. After processing \begin{frame} it looks forward until it finds \end{frame} doing no macro expansion, but simply absorbing tokens as it goes.
Yes, one might think to set up the presentation like
\startframes
...
\breakframe
...
\breakframe
...
\breakframe
\stopframes
but, unless you're wanting to absorb the whole presentation in one big swoop, the final part should be something as described above.
Is this so different from
\begin{frame}[t]
...
\end{frame}
\begin{frame}[t]
...
\end{frame}
\begin{frame}[t]
...
\end{frame}
to go into the burden of rewriting code already working?
A good text editor can spare you the typing and produce
\begin{frame}[t]
\end{frame}
with the pression of a couple of keys, also placing the cursor in the blank space.
- 1,121,712
\begin{frame}[t]\end{frame}is too much for you to type, just set one of the editor's shortcuts to insert it for you, most of the editors I know of can do this. – AboAmmar Jul 29 '20 at 23:41tfor all frames, use\documentclass[t]{beamer}(seebeamermanual, sec. 8.1). If you prefer command to environment, use\frame{<contents of frame env>}. – muzimuzhi Z Jul 30 '20 at 23:26