9

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

我目前通过将所有这些命令作为 (\newcommand \newcommand etc. etc.) 放在顶部然后手动从 tex 文件中删除“(”和“)”来处理这个问题。

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

例如,我将在 org 文件中添加以下内容:

: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

4 回答 4

6

在撰写本文时,这是一种适用于 Org、pdflatex 和 MathJax 的独立方式。确保抽屉(或至少LATEXMACROS抽屉)已导出(这是默认设置),然后在 Org 文件顶部附近插入:

#+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 文件 Org 构建不会包含我们的环境。

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

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

  • 这可能真的取决于版本:

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

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

于 2014-02-12T19:51:18.303 回答
3

我想出了如何自己做。请注意,这可能不是最优雅的解决方案,因为它没有将乳胶部分放在乳胶文件的开头(即在 \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))
)
于 2012-10-04T01:26:40.947 回答
3

替代解决方案(不是独立的),使用 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:

每当修改宏时执行此操作。

于 2014-06-27T17:37:24.267 回答
1

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

以下是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:
于 2017-02-28T23:36:52.287 回答