Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Customizing org-mode exports

Tags:

emacs

org-mode

So, I have been using org-mode for taking my research notes for some time now. I love how I can seamlessly export to both latex (for my papers) and html (for my blog). However, whenever I define macros with \newcommand with #+LATEX_HEADER, these do not show up in the HTML export at all.

I currently handle this by putting the all these commands as (\newcommand \newcommand etc. etc.) at the top and then manually removing the "(" and ")" from the tex file.

What I wish I could do was to keep a drawer for these commands and customize html and latex export of org mode to handle this drawer appropriately.

For example, I would add the following in the org file:

:LATEX_MACROS:
\newcommand{\norm}[1]{\lVert{#1}\rVert}
\newcommand{\abs}[1]{\lvert{#1}\rvert}
\newcommand{\half}{\frac{1}{2}}
:END:

And after export, this shows up in the latex file verbatim in header section and in the html file as

\(
\newcommand{\norm}[1]{\lVert{#1}\rVert}
\newcommand{\abs}[1]{\lvert{#1}\rvert}
\newcommand{\half}{\frac{1}{2}}
\)
like image 970
Shitikanth Avatar asked Oct 03 '12 22:10

Shitikanth


2 Answers

Alternative solution (not stand-alone), using Org's dynamic blocks.

  • It has none of the caveats of my original solution (because it generates what Org actually expects for LaTeX or HTML)
  • It's possible to edit the macros in LaTeX mode (C-c C-')

Callback

Create a file named org-dblock-write:block-macro.el with the following content and add it to Emacs' load path.

(defun org-dblock-write:block-macro (params)
  (let ((block-name (or (plist-get params :from) "macros"))
    (org-buf (current-buffer)))
    (with-temp-buffer
      (let ((tmp-buf (current-buffer)))
    (set-buffer org-buf)
    (save-excursion
      (org-babel-goto-named-src-block block-name)
      (org-babel-mark-block)
      (let ((mblock-begin (region-beginning))
            (mblock-end (region-end)))
        (set-buffer tmp-buf)
        (insert-buffer-substring org-buf mblock-begin mblock-end)))
    (set-buffer org-buf)
    (insert "#+BEGIN_HTML\n\\(\n")
    (insert-buffer-substring tmp-buf)
    (insert "\\)\n#+END_HTML\n")
    (set-buffer tmp-buf)
    (beginning-of-buffer)
    (while (re-search-forward "^" nil t)
      (replace-match "#+LATEX_HEADER: " nil nil))
    (set-buffer org-buf)
    (insert-buffer-substring tmp-buf)))))

Org file

Somewhere in the file, create:

  • A LaTeX source block named "macros" containing your macros
  • An empty block-macro dynamic block

You can change the name of the source block, and use a :from <custom-name> header argument in the dynamic block. Also, note the :exports none in the source block (usually you don't want to export the LaTeX source).

#+NAME: macros
#+BEGIN_SRC latex :exports none
  \newcommand\a{a}
  \def\b{b}
  \DeclareMathOperator\c{c}
#+END_SRC
#+BEGIN: block-macro
#+END:

Now use C-c C-c with the point on the dynamic block, and it will update to:

#+BEGIN: block-macro
#+BEGIN_HTML
\(
      \newcommand\a{a}
      \def\b{b}
      \DeclareMathOperator\c{c}
\)
#+END_HTML
#+LATEX_HEADER:       \newcommand\a{a}
#+LATEX_HEADER:       \def\b{b}
#+LATEX_HEADER:       \DeclareMathOperator\c{c}
#+LATEX_HEADER: 
#+END:

Do this whenever the macros are modified.

like image 190
Blout Avatar answered Nov 15 '22 02:11

Blout


I figured out how to do it myself. Note that this is perhaps not the most elegant solution since it does not place the latex part in the beginning of the latex file (i.e. outside \begin{document}), but it works well enough for me.

(setq org-export-blocks
  (cons '(latexmacro org-export-blocks-latexmacro) org-export-blocks))

(defun org-export-blocks-latexmacro (body &rest headers)
  (message "exporting latex macros")
  (cond
   ((eq org-export-current-backend 'html) (concat "\\(" body "\\)"))
   ((eq org-export-current-backend 'latex) body)
   (t nil))
)
like image 27
Shitikanth Avatar answered Nov 15 '22 02:11

Shitikanth