松手, 然后得到 PDF
省流版:
你只需要往 org 文件最后添加这样的一段:
* COMMENT Local Variables
# Local Variables:
# eval: (add-hook 'after-save-hook 'org-latex-export-to-pdf nil t)
# End:
或者是在 Emacs 配置中添加相应的 hook 即可, 你就可以体验到类似 Overleaf 的保存后立刻预览的功能. 如下图所示:
(注: 编译的过程是异步的, 理论上你并不需要像图中一样将鼠标移动到 Skim (PDF 预览器) 上, Skim 在开启 sync 同步后会自动更新本地的 PDF 更新)
稍微详细一点的解释
org-mode 的文件实际上是一个完全可编程的东西, 你完全可以把它当作一个强悍的代码.
在上面的 Local Variables
中, 大概是这样的一个感觉:
* COMMENT 这个带有 COMMENT 标记的 section 表示这部分不会被作为 org 的正文
# Local Variables:
# eval: 执行 Emacs 的 ELISP 代码
# End:
其中 Local Variables
会在打开文件的时候自动载入, 也就是会在打开文件的时候执行 ELISP 代码 (因为可能会有安全问题, 所以一般都会提问你一下)
能不能更有意思一点?
比如说你需要做一些枯燥的调参的活, 来观察调参后某段代码的运行结果如何, 假设你的代码如下:
#+name: lorenz-system-dt
#+headers: :var sigma=10 rho=28 beta=(/ 8 3)
#+headers: :var x0=0 y0=1 z0=0
#+headers: :var dt=0.01 time=100 method='forward-euler
#+headers: :var out-path="./lorenz-system-dt.png"
#+headers: :results file :exports results
#+begin_src lisp
(with-present-to-file
(plots horizontal-layout-presentation)
(out-path :width 1500 :height 500)
(let* ((phase (eval `(,method ((x ,x0) (y ,y0) (z ,z0))
((* ,sigma (- y x))
(- (* x (- ,rho z)) y)
(- (* x y) (* ,beta z)))
:dt ,dt :time ,time))))
(add-component plots 'xy-trajectory
(with-present (plot plot :margin 5 :x-label "x" :y-label "y")
(add-plot-data plot
(line-plot-pane points-list
:color +蛋青+)
(loop for (x y -) in phase
collect (list x y))))
0.33)
(add-component plots 'xz-trajectory
(with-present (plot plot :margin 5 :x-label "x" :y-label "z")
(add-plot-data plot
(line-plot-pane points-list
:color +大红+)
(loop for (x - z) in phase
collect (list x z))))
0.33)
(add-component plots 'yz-trajectory
(with-present (plot plot :margin 5 :x-label "y" :y-label "z")
(add-plot-data plot
(line-plot-pane points-list
:color +大红官绿+)
(loop for (- y z) in phase
collect (list y z))))
0.33)))
out-path
#+end_src
于是在 org-file 中你只需要如下即可调用这段绘图代码:
#+name: rk4-lorenz-system
#+call: lorenz-system-dt(method='rk4, out-path="./lorenz-system-rk4.png", dt=0.01)
听起来感觉有点麻烦? 那么再来看看如下的例子:
你用 C 写了一个随机数生成程序, 与其用 Python 再写一个读取数据的函数, 不如直接使用如下的方式来进行调用:
#+name: c-random
#+headers: :includes <stdlib.h> <time.h> <stdio.h>
#+headers: :var n=10 :results output table
#+begin_src C
srand(time(NULL));
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
printf("%d ", rand());
}
printf("\n");
}
#+end_src
#+name: python-sum
#+headers: :var matrix=[[]]
#+begin_src python
return sum(sum(row) for row in matrix)
#+end_src
#+call: python-sum(c-random(10))
#+RESULTS:
: 107200076097
这样理论上来说你不论用什么语言都可以计算了, 或者说, 那个简单就用哪个, 这对于快速原型代码设计会非常轻松.
(注: 上面的例子是一个简化的例子)