On Mon, Feb 19 2024, Ihor Radchenko <yanta...@posteo.net> wrote:

> Leo Butler <leo.but...@umanitoba.ca> writes:
>
>>> What about not adding BEAMER_FRAME, but instead adding org-lint checker
>>> that will detect when frame text contains the problematic \end{orgframe}?
>>
>> Ok, thanks for your feedback. I have modified the patch along the lines
>> you suggested. It is attached.
>
> Thanks!
> It looks like you left over some parts from the previous patch version.
>
>> (org-beamer--format-frame): Introduce the new property, :BEAMER_FRAME.
>
> ... like this.
>
>> (org-beamer--frame-environments): New variable and function.  The
>> variable holds a list of names of frame environments found while
>> formatting frames.  The function generates the LaTeX code to define
>> each new frame environment.
>> (org-beamer-template): Add a call to `org-beamer--frame-environments'
>> to insert the environment definitions into the beamer document.
>
> And since we only have a single alternative environment in this version
> of the patch, `org-beamer--frame-environments' does not appear to be
> necessary.
>
>> +(defcustom org-beamer-frame-environment "orgframe"
>> +  "Name of the beamer frame environment."
>> +  :group 'org-export-beamer
>> +  :type '(string :tag "Beamer frame"))
>
> It would be nice to provide a mode detailed explanation about the
> purpose of this custom option.
>
>> +(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.") result))
>> +      result)))
>
> ... and to link this org-lint warning to the
> `org-beamer-frame-environment' docstring.

Thanks for your comments.

I think the attached patch addresses each of your points. It's not clear
to me what you mean by "link(ing) this org-lint warning to the
`org-beamer-frame-environment' docstring", but I have expanded the
warning include mention of this variable.

Leo

From 70262bc2469536eeb3aaec926ec71530cfaeca79 Mon Sep 17 00:00:00 2001
From: Leo Butler <leo.but...@umanitoba.ca>
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

Reply via email to