From 70262bc2469536eeb3aaec926ec71530cfaeca79 Mon Sep 17 00:00:00 2001 From: Leo Butler Date: Thu, 25 Jan 2024 09:48:20 -0600 Subject: [PATCH] lisp/ox-beamer.el: customize the beamer frame environment name * lisp/ox-beamer.el (org-beamer-frame-environment): A new customize variable. It contains the name of an environment that serves as an alias for the beamer frame environment. (org-beamer-template): Add a call to `org-beamer--frame-environments' to insert the environment definitions into the beamer document. * lisp/org-lint.el (org-lint-beamer-frame): Check the body of each frame for an occurrence of \begin{orgframe} or \end{orgframe}, or whatever environment name is in `org-beamer-frame-environment' [4]. The warning includes advice to see `org-beamer-frame-environment'. Rationale: Code with \begin{frame} or \end{frame} cannot be embedded in a verbatim environment inside a beamer frame due to a design decision made by the beamer developers [1]. As suggested in that report, defining an alias for the beamer frame environment will allow such verbatim examples to compile correctly [2]. This solution also works with instances of \againframe. Refs: [1] https://github.com/josephwright/beamer/issues/360 [2] https://github.com/josephwright/beamer/issues/360#issuecomment-708705250 [3] https://list.orgmode.org/orgmode/87le8eg1hs.fsf@localhost/T/ [4] https://list.orgmode.org/orgmode/87il38i5tb.fsf@localhost/T/ --- lisp/org-lint.el | 15 +++++++++++++++ lisp/ox-beamer.el | 28 ++++++++++++++++++++-------- 2 files changed, 35 insertions(+), 8 deletions(-) diff --git a/lisp/org-lint.el b/lisp/org-lint.el index 4d2a55d15..91ee2eb2a 100644 --- a/lisp/org-lint.el +++ b/lisp/org-lint.el @@ -1507,6 +1507,17 @@ AST is the buffer parse tree." ((memq (org-element-property :type deadline) '(inactive inactive-range)) (list (org-element-begin planning) "Inactive timestamp in DEADLINE will not appear in agenda.")) (t nil)))))) + +(defun org-lint-beamer-frame (ast) + "Check for occurrences of begin or end frame." + (org-with-point-at ast + (goto-char (point-min)) + (let (result) + (while (re-search-forward + (concat "\\\\\\(begin\\|end\\){" org-beamer-frame-environment "}") nil t) + (push (list (match-beginning 0) "Beamer frame name may cause error when exporting. See `org-beamer--frame-environment'.") result)) + result))) + ;;; Checkers declaration @@ -1787,6 +1798,10 @@ AST is the buffer parse tree." "Report $ that might be treated as LaTeX fragment boundary." #'org-lint-LaTeX-$-ambiguous :categories '(markup) :trust 'low) +(org-lint-add-checker 'beamer-frame + "Report that frame text contains beamer frame environment." + #'org-lint-beamer-frame + :categories '(export) :trust 'low) (org-lint-add-checker 'timestamp-syntax "Report malformed timestamps." #'org-lint-timestamp-syntax diff --git a/lisp/ox-beamer.el b/lisp/ox-beamer.el index 571b9c239..c65166e61 100644 --- a/lisp/ox-beamer.el +++ b/lisp/ox-beamer.el @@ -148,6 +148,14 @@ which is replaced with the subtitle." :package-version '(Org . "8.3") :type '(string :tag "Format string")) +(defcustom org-beamer-frame-environment "orgframe" + "Name of the alternative beamer frame environment. +In frames marked as fragile, this environment is used in place of +the usual frame environment. This permits insertion of a beamer +frame inside example blocks." + :group 'org-export-beamer + :type '(string :tag "Beamer frame")) + ;;; Internal Variables @@ -408,12 +416,14 @@ used as a communication channel." "Format HEADLINE as a frame. CONTENTS holds the contents of the headline. INFO is a plist used as a communication channel." - (let ((fragilep - ;; FRAGILEP is non-nil when HEADLINE contains an element - ;; among `org-beamer-verbatim-elements'. - (org-element-map headline org-beamer-verbatim-elements 'identity - info 'first-match))) - (concat "\\begin{frame}" + (let* ((fragilep + ;; FRAGILEP is non-nil when HEADLINE contains an element + ;; among `org-beamer-verbatim-elements'. + (org-element-map headline org-beamer-verbatim-elements 'identity + info 'first-match)) + (frame (or (and fragilep org-beamer-frame-environment) + "frame"))) + (concat "\\begin{" frame "}" ;; Overlay specification, if any. When surrounded by ;; square brackets, consider it as a default ;; specification. @@ -480,7 +490,7 @@ used as a communication channel." ;; output. (if (not fragilep) contents (replace-regexp-in-string "\\`\n*" "\\& " (or contents ""))) - "\\end{frame}"))) + "\\end{" frame "}"))) (defun org-beamer--format-block (headline contents info) "Format HEADLINE as a block. @@ -814,7 +824,6 @@ contextual information." (org-export-get-reference radio-target info) text)) - ;;;; Template ;; ;; Template used is similar to the one used in `latex' backend, @@ -834,6 +843,9 @@ holding export options." (org-latex--insert-compiler info) ;; Document class and packages. (org-latex-make-preamble info) + ;; Define the alternative frame environment. + (format "\\newenvironment<>{%s}[1][]{\\begin{frame}[environment=%1$s,#1]}{\\end{frame}}\n" + org-beamer--frame-environment) ;; Insert themes. (let ((format-theme (lambda (prop command) -- 2.43.0