0

I want to quickly wrap certain environments my cursor is within with text.

In my specific situation, I want to wrap the frame environment with the text

\makeatletter
\gdef\beamer@currentmode{beamer}
\makeatother

and

\makeatletter
\gdef\beamer@currentmode{handout}
\makeatother

Here's a MWE to illustrate my situation:

 1  \documentclass[handout]{beamer}
 2  
 3  \begin{document}
 4  
 5  \begin{frame}
 6  
 7    \frametitle{Foo}
 8  
 9    \begin{block}{First Block}<+->
10      Foo bar.
11    \end{block}
12  
13    \begin{block}{Second Block}<+->
14      Foo bar.
15    \end{block}
16  
17  \end{frame}
18  
19  \makeatletter
20  \gdef\beamer@currentmode{beamer}
21  \makeatother
22  \begin{frame}
23  
24    \frametitle{Bar}
25  
26    \begin{block}{First Block}<+->
27      Foo \uncover<+->{bar.}
28    \end{block}
29  
30    \begin{block}{Second Block}<+->
31      Spam \uncover<+->{eggs.}
32    \end{block}
33  
34  \end{frame}
35  \makeatletter
36  \gdef\beamer@currentmode{handout}
37  \makeatother
38  
39  \end{document}

If my cursor is anywhere between lines 5 and 17, then issuing my desired command would produce:

 1  \documentclass[handout]{beamer}
 2  
 3  \begin{document}
 4  
 5  \makeatletter
 6  \gdef\beamer@currentmode{beamer}
 7  \makeatother
 8  \begin{frame}
 9  
10    \frametitle{Foo}
11  
12    \begin{block}{First Block}<+->
13      Foo bar.
14    \end{block}
15  
16    \begin{block}{Second Block}<+->
17      Foo bar.
18    \end{block}
19  
20  \end{frame}
21  \makeatletter
22  \gdef\beamer@currentmode{handout}
23  \makeatother
24  
25  \makeatletter
26  \gdef\beamer@currentmode{beamer}
27  \makeatother
28  \begin{frame}
29  
30    \frametitle{Bar}
31  
32    \begin{block}{First Block}<+->
33      Foo \uncover<+->{bar.}
34    \end{block}
35  
36    \begin{block}{Second Block}<+->
37      Spam \uncover<+->{eggs.}
38    \end{block}
39  
40  \end{frame}
41  \makeatletter
42  \gdef\beamer@currentmode{handout}
43  \makeatother
44  
45  \end{document}

Ideally, this command would toggle the wrapping, so with the cursor anywhere between lines 19 and 37 in the original file would produce:

 1  \documentclass[handout]{beamer}
 2  
 3  \begin{document}
 4  
 5  \begin{frame}
 6  
 7    \frametitle{Foo}
 8  
 9    \begin{block}{First Block}<+->
10      Foo bar.
11    \end{block}
12  
13    \begin{block}{Second Block}<+->
14      Foo bar.
15    \end{block}
16  
17  \end{frame}
18  
19  \begin{frame}
20  
21    \frametitle{Bar}
22  
23    \begin{block}{First Block}<+->
24      Foo \uncover<+->{bar.}
25    \end{block}
26  
27    \begin{block}{Second Block}<+->
28      Spam \uncover<+->{eggs.}
29    \end{block}
30  
31  \end{frame}
32  
33  \end{document}

Is this doable with the tools provided by AUCTeX?

3 Answers 3

1

You can define a new environment which wraps the frame environment with the code you want, so something like this in your preamble should work:

\makeatletter
\newenvironment{Frame}[1][]{%
  \gdef\beamer@currentmode{beamer}%
  \begin{frame}[environment=Frame,#1]%
}{%
  \end{frame}%
  \gdef\beamer@currentmode{handout}%
}
\makeatother

and then use the Frame environment instead of frame.

If you want to insert the code into your file, you have to write a function which can look like this:

(defun my/LaTeX-beamer-toggle ()
  (interactive)
  (let ((p (point-marker))
        (s (make-marker))
        (e (make-marker)))
    ;; Get us into frame-env top-level:
    (while (not (string= (LaTeX-current-environment) "frame"))
      (LaTeX-find-matching-begin))
    ;; Now find the matching begin of "frame"
    (LaTeX-find-matching-begin)
    (if (save-excursion
          (and (search-backward "\\makeatletter"
                                (line-beginning-position -5) t)
               (setq s (point))
               (search-forward "\\makeatother"
                               (line-beginning-position 5) t)
               (setq e (point))))
        (delete-region s e)
      (insert "\n"
              "\\makeatletter"
              "\n"
              "\\gdef\\beamer@currentmode{beamer}"
              "\n"
              "\\makeatother"
              "\n"))
    (goto-char p)
    ;; Get us into frame-env top-level:
    (while (not (string= (LaTeX-current-environment) "frame"))
      (LaTeX-find-matching-end))
    ;; Now find the matching end of "frame"
    (LaTeX-find-matching-end)
    (if (save-excursion
          (and (search-forward "\\makeatletter"
                               (line-end-position 5) t)
               (setq s (match-beginning 0))
               (search-forward "\\makeatother"
                               (line-end-position 4) t)
               (setq e (point))))
        (delete-region s e)
      (insert "\n"
              "\\makeatletter"
              "\n"
              "\\gdef\\beamer@currentmode{handout}"
              "\n"
              "\\makeatother"
              "\n"))
    (goto-char p)
    (set-marker p nil)
    (set-marker s nil)
    (set-marker e nil)))

In your file, do M-x my/LaTeX-beamer-toggle RET and see if it works as expected.

0

I am not familiar with TeX. But I can answer the "wrap a BODY TEXT with a PREAMBLE and POSTAMBLE" part.

  1. Copy the below snippet to an empty *scratch* buffer, and do M-x eval-buffer RET
(require 'tempo)
(setq tempo-interactive t)
(tempo-define-template "wrap-1"
               '("
\\makeatletter
\\gdef\\beamer@currentmode{beamer}
\\makeatother
"
                         n>
             r
             n>
             "
\\makeatletter
\\gdef\\beamer@currentmode{handout}
\\makeatother
" > %))

  1. Mark a region of text, and do M-x tempo-template-wrap-1 RET. Your text will be wrapped.

For example I started with this text

body

and did M-x tempo-template-wrap-1 RET when the above body text was active. I got this

\makeatletter
\gdef\beamer@currentmode{beamer}
\makeatother

body

\makeatletter
\gdef\beamer@currentmode{handout}
\makeatother

You can read more about tempo library here David's Elisp hacks or here EmacsWiki: Tempo Mode.

Or

You can read the info manual online at Info manual for tempo library, or download it, and read it right in your Emacs with C-u C-h i temp.info RET (C-u M-x info RET temp.info RET)

Or

If tempo is too old school for you, I am sure there are yasnippet recipes for what you want to achieve. Keywords to search for are "template", "snippet" etc

1
  • if you think that moving my paragraph is fragile, then you can add % begin wrap to the beginning of your preamble, and % end wrap to the end of postable, and use C-r % begin wrap and C-s % end wrap to do kill the preamble + postamble part. The answer above uses big motion commands and keyboard macro, and don't forget the mode-specific menu bar commands.
    – user31220
    Commented Jul 19, 2022 at 8:06
0

This answers the unwrap part

Overview

| M-x package-initialize  <return>        | package-initialize        |
| C-x C-x C-f test.tex  <return>          | find-file                 |
| M-x display-line-numbers-mode  <return> | display-line-numbers-mode |
| M-g M-g 27  <return>                    | goto-line                 |
| C-2  C-c .                              | LaTeX-mark-environment    |
| C-u C-x r s a                           | copy-to-register  ?a      |
| C-<up>                                  | backward-paragraph        |
| C-SPC                                   | set-mark-command          |
| C-<down>                                | forward-paragraph         |
| C-w                                     | kill-region               |
| C-x r i a                               | insert-register   ?a      |

Menu Bar for LaTeX

Detailed Answer

  1. Copy the below snippet to test.tex.
\documentclass[handout]{beamer}

\begin{document}

\begin{frame}
  
  \frametitle{Foo}
  
  \begin{block}{First Block}<+->
    Foo bar.
  \end{block}
  
  \begin{block}{Second Block}<+->
    Foo bar.
  \end{block}
  
\end{frame}

\makeatletter
\gdef\beamer@currentmode{beamer}
\makeatother
\begin{frame}
  
  \frametitle{Bar}
  
  \begin{block}{First Block}<+->
    Foo \uncover<+->{bar.}
  \end{block}
  
  \begin{block}{Second Block}<+->
    Spam \uncover<+->{eggs.}
  \end{block}
  
\end{frame}
\makeatletter
\gdef\beamer@currentmode{handout}
\makeatother

\end{document}
  1. emacs -Q
  2. M-x package-initialize
  3. C-x b *scratch*. Copy the below snippet and do M-x eval-buffer RET.
(defalias 'unwrap
   (kmacro "C-u C-x r s a C-<up> C-SPC C-<down> C-w C-x r i a"))
  1. C-x C-f test.tex RET.
  2. M-x display-line-numbers-mode
  3. M-g M-g 27
  4. C-2 C-c .
  5. M-x unwrap RET
  6. Profit
1
  • If you think that moving my paragraph is fragile, then you can add % begin wrap to the beginning of your preamble, and % end wrap to the end of postamble, and use search motion commands---C-r % begin wrap and C-s % end wrap---to kill the bare preamble + postamble part. The answer above uses big motion commands (the keybinding of these motion commands are standard across all modes), keyboard macro, and don't forget the mode-specific menu bar commands. If you are serious about Emacs these are the parts you need to focus on.
    – user31220
    Commented Jul 19, 2022 at 8:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.