Hi

I have split out this part from the general LaTeX/Beamer structure
discussion. The patch makes the code more readable (factored out function
that is called only when the class isn't lta-talk) and it provides use with
a fine-grain control (LaTeX code that must go immediately before
\usetheme{}).

With this in place, we can start talking about the high level sequence in
any LaTeX document (including presentations).


/PA
ox-latex & ox-beamer maintainer
--
Fragen sind nicht da, um beantwortet zu werden,
Fragen sind da um gestellt zu werden
Georg Kreisler

"Sagen's Paradeiser" (ORF: Als Radiohören gefährlich war) => write BE!
Year 2 of the New Koprocracy

This was produced by a human (implied virtues and weaknesses acknowledged)
I'd hate this being fed to any form of AS (sorry AI)...
From 61ca9eec6d3a496f7860e77f292c16d90e77a619 Mon Sep 17 00:00:00 2001
From: "Pedro A. Aranda" <[email protected]>
Date: Mon, 6 Jul 2026 08:19:19 +0200
Subject: [PATCH] ox-beamer: New keywork BEAMER_THEME_PRE

* doc/org-manual.org (Beamer specific export settings): Refine note on
THEME keywords.  Add BEAMER_THEME_PRE.  Fix language nit.
* etc/ORG-NEWS: Announce BEAMER_THEME_PRE.
* lisp/ox-beamer.el (exporter): Add BEAMER_THEME_PRE keyword.
(org-beamer--theme-header): Factor out BEAMER_THEME keyword handling and
prepend BEAMER_THEME_PRE to resulting string.
(org-beamer-template): Add result from (org-beamer--theme-header) for
LaTeX class "beamer" only.
* testing/lisp/test-ox-beamer.el (test-ox-beamer/beamer-theme-pre): New
test for BEAMER_THEME_PRE.
---
 doc/org-manual.org             | 17 +++++++++--
 etc/ORG-NEWS                   |  6 ++++
 lisp/ox-beamer.el              | 52 +++++++++++++++++++++-------------
 testing/lisp/test-ox-beamer.el | 29 +++++++++++++++++++
 4 files changed, 81 insertions(+), 23 deletions(-)

diff --git a/doc/org-manual.org b/doc/org-manual.org
index bda84c49c..cd8903a7e 100644
--- a/doc/org-manual.org
+++ b/doc/org-manual.org
@@ -13156,8 +13156,11 @@ documentation]].

 Beamer export backend has several additional keywords for customizing
 Beamer output.  These keywords work similar to the general options
-settings (see [[*Export Settings]]). *Note:* =BEAMER_..._THEME=
-keywords do not apply to =ltx-talk= and will be ignored.
+settings (see [[*Export Settings]]).
+
+#+texinfo: @noindent
+*Note:* Theme-related =BEAMER_...= keywords do not apply to =ltx-talk=
+and will be ignored.

 - =BEAMER_THEME= ::

@@ -13183,6 +13186,14 @@ keywords do not apply to =ltx-talk= and will be ignored.
   #+cindex: @samp{BEAMER_OUTER_THEME}, keyword
   The Beamer outer theme.

+- =BEAMER_THEME_PRE= ::
+
+  #+cindex: @samp{BEAMER_THEME_PRE}, keyword
+  Arbitrary lines that must appear immediately before the Beamer theme
+  declaration:
+
+  : #+BEAMER_THEME_PRE: \usepackage[total={16cm,9cm}]{geometry}
+
 - =BEAMER_HEADER= ::

   #+cindex: @samp{BEAMER_HEADER}, keyword
@@ -13220,7 +13231,7 @@ keywords do not apply to =ltx-talk= and will be ignored.

   #+cindex: @samp{LATEX_CLASS}, keyword
   The LaTeX class to use. Implicitly set to =beamer=. Set it
-  explicitly to =ltx-talk= to use this class:
+  explicitly to =ltx-talk= to use this class instead:

   #+BEGIN_SRC org
 ,#+LATEX_CLASS: ltx-talk
diff --git a/etc/ORG-NEWS b/etc/ORG-NEWS
index 5f5168e33..ad292de08 100644
--- a/etc/ORG-NEWS
+++ b/etc/ORG-NEWS
@@ -154,6 +154,12 @@ Presentations written with Beamer and ltx-talk are mostly portable,
 except that Beamer theme information is ignored when using ltx-talk
 and some environments listed in the manual are not supported.

+*** ox-beamer.el: New keyword BEAMER_THEME_PRE
+
+The new keyword allows to add arbitrary lines just before the Beamer theme
+declaration.  It allows you to fine-tune your Beamer theme settings
+further.
+
 ** New and changed options

 # Changes dealing with changing default values of customizations,
diff --git a/lisp/ox-beamer.el b/lisp/ox-beamer.el
index f5cf1a896..b4157bfe5 100644
--- a/lisp/ox-beamer.el
+++ b/lisp/ox-beamer.el
@@ -275,6 +275,7 @@ (org-export-define-derived-backend 'beamer 'latex
     (:beamer-font-theme "BEAMER_FONT_THEME" nil nil t)
     (:beamer-inner-theme "BEAMER_INNER_THEME" nil nil t)
     (:beamer-outer-theme "BEAMER_OUTER_THEME" nil nil t)
+    (:beamer-theme-pre "BEAMER_THEME_PRE" nil nil newline)
     (:beamer-header "BEAMER_HEADER" nil nil newline)
     (:beamer-environments-extra nil nil org-beamer-environments-extra)
     (:beamer-frame-default-options nil nil org-beamer-frame-default-options)
@@ -880,6 +881,33 @@ (defun org-beamer-radio-target (radio-target text info)

 ;;;; Template
 ;;
+;; Factored out
+(defun org-beamer--theme-header (info)
+  "Return the theme related configuration from INFO as a string."
+  ;; This function was factored out from org-beamer-template
+  ;; Prepends :beamer-theme-pre if it exists
+  (let ((theme-pre (plist-get info :beamer-theme-pre)))
+    (concat theme-pre
+            (and theme-pre "\n")
+            (let ((format-theme
+	           (lambda (prop command)
+	             (let ((theme (plist-get info prop)))
+		       (when theme
+		         (concat command
+			         (if (not (string-match "\\[.*\\]" theme))
+			             (format "{%s}\n" theme)
+			           (format "%s{%s}\n"
+				           (match-string 0 theme)
+				           (org-trim
+				            (replace-match "" nil nil theme))))))))))
+              (mapconcat (lambda (args) (apply format-theme args))
+		         '((:beamer-theme "\\usetheme")
+		           (:beamer-color-theme "\\usecolortheme")
+		           (:beamer-font-theme "\\usefonttheme")
+		           (:beamer-inner-theme "\\useinnertheme")
+		           (:beamer-outer-theme "\\useoutertheme"))
+		         "")))))
+;;
 ;; Template used is similar to the one used in `latex' backend,
 ;; excepted for the table of contents and Beamer themes.

@@ -905,26 +933,10 @@ (defun org-beamer-template (contents info)
      (when (plist-get info :beamer-define-frame)
        (format "\\newenvironment<>{%s}[1][]{\\begin{frame}#2[environment=%1$s,#1]}{\\end{frame}}\n"
                org-beamer-frame-environment))
-     ;; Insert themes.
-     (unless (equal beamer-class "ltx-talk")
-       (let ((format-theme
-	      (lambda (prop command)
-	        (let ((theme (plist-get info prop)))
-		  (when theme
-		    (concat command
-			    (if (not (string-match "\\[.*\\]" theme))
-			        (format "{%s}\n" theme)
-			      (format "%s{%s}\n"
-				      (match-string 0 theme)
-				      (org-trim
-				       (replace-match "" nil nil theme))))))))))
-         (mapconcat (lambda (args) (apply format-theme args))
-		    '((:beamer-theme "\\usetheme")
-		      (:beamer-color-theme "\\usecolortheme")
-		      (:beamer-font-theme "\\usefonttheme")
-		      (:beamer-inner-theme "\\useinnertheme")
-		      (:beamer-outer-theme "\\useoutertheme"))
-		    "")))
+     ;; Insert theme info when class is "beamer".
+     ;; ltx-talk themes seem to be regular classes.
+     (and (not (equal beamer-class "ltx-talk"))
+          (org-beamer--theme-header info))
      ;; Possibly limit depth for headline numbering.
      (let ((sec-num (plist-get info :section-numbers)))
        (when (integerp sec-num)
diff --git a/testing/lisp/test-ox-beamer.el b/testing/lisp/test-ox-beamer.el
index 03e6d59d5..660af0854 100644
--- a/testing/lisp/test-ox-beamer.el
+++ b/testing/lisp/test-ox-beamer.el
@@ -281,5 +281,34 @@ (ert-deftest test-ox-beamer/beamer-verb-frame ()
      (org-test-ignore-duplicate
       (should (search-forward "\\end{frame}\n" nil t))))))

+(ert-deftest test-ox-beamer/beamer-theme-pre ()
+  "Test that the theme can be preceeded by arbitrary LaTeX
+using BEAMER_THEME_PRE."
+  (org-test-with-exported-text
+   'beamer
+   "#+STARTUP: beamer
+#+OPTIONS: toc:nil H:2 title:t
+#+LATEX_CLASS_OPTIONS: [presentation,11pt,t]
+#+TITLE: Testing =BEAMER_THEME_PRE=
+#+BEAMER_THEME_PRE: \\usepackage[total={16cm,9cm},
+#+BEAMER_THEME_PRE: top=1.2in, left=0.9in, includefoot]{geometry}
+#+BEAMER_THEME: Boadilla
+#+BEAMER_INNER_THEME: circles
+
+* A section
+** A frame
+- First
+- Second
+- Third
+"
+     ;; (message "--> \n%s" (buffer-string))
+     (goto-char (point-min))
+     (save-excursion
+       (should (search-forward "\\documentclass[presentation,11pt,t]{beamer}" nil t))
+       (should (search-forward "\\usepackage[total={16cm,9cm}," nil t))
+       (should (search-forward "top=1.2in, left=0.9in, includefoot]{geometry}" nil t))
+       (should (search-forward "\\usetheme{Boadilla}" nil t))
+       (should (search-forward "\\useinnertheme{circles}" nil t)))))
+
 (provide 'test-ox-beamer)
 ;;; test-ox-beamer.el ends here
--
2.43.0

Reply via email to