自定义组织模式导出

时间:2012-10-03 22:15:16

标签: emacs org-mode

所以,我一直在使用org-mode来研究我的研究笔记。我喜欢如何无缝导出乳胶(对于我的论文)和html(对于我的博客)。但是,每当我使用带有#+ LATEX_HEADER的\ newcommand定义宏时,这些都不会显示在HTML导出中。

我目前通过将所有这些命令设置为来处理此问题 (\ newcommand \ newcommand等等) 在顶部,然后手动删除tex文件中的“(”和“)”。

我希望我能做的就是为这些命令保留一个抽屉,并自定义组织模式的html和latex导出以适当地处理这个抽屉。

例如,我会在组织文件中添加以下内容:

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

导出后,这会在标题部分逐字显示在乳胶文件中 并在html文件中

\(
\newcommand{\norm}[1]{\lVert{#1}\rVert}
\newcommand{\abs}[1]{\lvert{#1}\rvert}
\newcommand{\half}{\frac{1}{2}}
\)

4 个答案:

答案 0 :(得分:3)

在撰写本文时,这是一种与Org,pdflatex和MathJax一起使用的独立方式。确保导出抽屉(或至少是LATEXMACROS抽屉)(这是默认值),然后插入组织文件顶部附近:

#+OPTIONS: toc:nil
#+DRAWERS: LATEXMACROS ...

:LATEXMACROS:
@@html:<div style="display: none">@@
\(
\global\def\mymacro{...}
\global\def\mymacrow2args#1#2{...}
...
\)
@@html:</div>@@
:END:

#+TOC: headlines

这解决了以下问题:

  • 我们必须使用数学环境(此处为\( ... \)),否则Org会转义TeX语法。

  • 我们不能使用\newcommand,因为LaTeX希望它们在序言中并且MathJaX不会接收它。 \newcommand可以在序言之外使用,但是LaTeX(与MathJax不同)将定义的宏限制为当前的数学环境。我们通常希望在文件中的任何位置使用它们。

  • 我们不能使用普通\def,因为它在范围界定方面类似于\newcommand(MathJax是全局的,LaTeX是本地的)。我们不能使用\xdef,因为MathJax不知道它。

  • MathJax不知道\global,但这无法阻止它使用全局的\def。但是,它会为网页中的每个\global打印一个红色警告。为了摆脱它们,我们将数学环境放在未显示的HTML部分中。

  • 对于MathJax,不会及时为其默认位置的内容表定义宏。如果您在标题中使用宏并想要TOC,请使用#+OPTIONS: toc:nil停用默认值,然后使用#+TOC: headlines在抽屉后手动添加。

注意事项:

  • 无法预览使用自定义宏的乳胶碎片,因为小的TeX文件组织构建将不包含我们的环境。

  • \newcommand不同,\def默默地替换任何内容。此外,它的语法略有不同。

  • 数学环境在pdflatex的输出中占用一些垂直空间,所以我们必须把它放在无关紧要的地方(例如在第一个标题之前)。

  • 这可能与版本有关:

    • Org模式可能会更好地导出LaTeX宏(例如,在解析#+LATEX_HEADER时更聪明地将它们发送到MathJax,提供新的导出选项,而不是转义\newcommand并将它们放入正确处理序言。)

    • MathJax可能会开始接受\xdef作为\def的别名或忽略\global(因此不再需要HTML部分技巧)。

答案 1 :(得分:2)

我想出了自己该怎么做。请注意,这可能不是最优雅的解决方案,因为它不会将乳胶部分放在乳胶文件的开头(即在\ begin {document}之外),但它对我来说效果很好。

(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))
)

答案 2 :(得分:2)

使用Org的动态块替代解决方案(不是独立的)。

  • 它没有我原始解决方案的任何警告(因为它生成了Org实际上对LaTeX或HTML的期望)
  • 可以在LaTeX模式(C-c C-'
  • 中编辑宏

回调

使用以下内容创建名为org-dblock-write:block-macro.el的文件,并将其添加到Emacs的加载路径。

(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)))))

组织文件

文件中的某处,创建:

  • 包含您的宏的名为“宏”的LaTeX源块
  • block-macro动态区块

您可以更改源块的名称,并在动态块中使用:from <custom-name>标头参数。另外,请注意源块中的:exports none(通常您不想导出LaTeX源)。

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

现在将C-c C-c与动态块上的点一起使用,它将更新为:

#+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:

每当修改宏时都这样做。

答案 3 :(得分:0)

我通常有一个包含许多自定义定义的文件,我将其重复用于许多文档,我也想在我的组织文档中使用它。

以下是Blout's答案的修改,请阅读他的答案以获取更多信息。

定义宏

(defun org-dblock-write:insert-latex-macros (params)
  (let ((text)
    (file (plist-get params :file)))
    (with-temp-buffer
      (insert-file file)
      (setq text (split-string (buffer-string) "\n" t)))
    (insert (mapconcat (lambda (str) (concat "#+LATEX_HEADER: " str)) text "\n"))
    (insert "\n#+BEGIN_HTML\n\\(\n")
    (insert (mapconcat 'identity text "\n"))
    (insert "\n\\)\n#+END_HTML")))

用法

档案macros.tex

\newcommand\a{a}
\def\b{b}
\DeclareMathOperator\c{c}

在组织文件中:

#+BEGIN: insert-latex-macros :file "macros.tex"
#+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: