Emacs让编程多一种可能

原文Babel: Introduction, 由 Eric Schulte , Dan Davison, Tom Dye 编辑,维护。本文只做学习之用。本文章同时发表在自己的私人博客里,欢迎前往阅读。

序言<a id="introduction"></a>

Bable 可让许多不同的语言工作一起。 编程语言生活在自然语言的 Org-mode 文档的代码块之中。 一个数据片段可从一个表格传递给一个 Pythoh 代码块,然后可能再转移到一个 R 代码块, 最终以数据块被嵌入段落的中间而终结,或者通过 gnuplot 代码块生成图片嵌入在文档中。

通过扩展 Org-mode, 使其具有编辑,导出和执行源代码的功能, BabelOrg-mode 变成了文学编程和可重复性研究的工具。

Babel 通过提供以下特性来增强 Org-mode对代码代码块的支持: Babel augments Org-mode support for code blocks by providing:

  • 代码块的交互和执行结果导出
  • 代码块可像函数一样可参数化,引用其他代码块,可被远程调用
  • 拼接,导出源代码到文件支持文学编程。

概述<a id="sec-2"></a>

Babel 在几个不同的方面提供了新的功能,不同的人可能想在不同的地方开始。

  • Org-mode 中使用代码块: 如果目前你还不知道怎么在 Org-mode 中创建代码块, 或者不清楚怎样在 Org-mode 的缓冲区和语言主模式编辑缓冲区(the language major-mode edit buffer)之间切换, 那么你需要应该看看Org 手册中的相关部分 和 下面的代码块章节, 尝试下,然后赶紧回来。
  • 执行代码: Babel 的核心是能够在 Org-mode 代码块中执行代码, 从其他块和表格获取输入,并输出到更多的块和表。 从源代码执行开始描述。
  • Literate Programming: 程序员编写的代码,通常以其他方式执行(例如从命令行或将其引入到交互式会话中), 那么对 Babel 的简单介绍就是将代码放在 Org-mode 文件的代码块中, 然后使用 BabelLiterate Programming 支持从 Org-mode 文件中扩展提取源代码。

所有这些用例以及 Babel 功能的详尽文档都被涵盖在 Org 手册的 使用源代码中。

初始配置<a id="getting-started"></a>

If you have a working Emacs installation, then getting started with Babel is a simple process.

  1. If you are running Emacs24 a current version of Org-mode with Babel is already available by default. Otherwise, it is strongly recommended that you update to the latest version of Org-mode by keeping current with Org-mode development. As of Org-mode 7.0, Babel is included as part of Org-mode.

  2. Optionally activate the subset of languages that you will want to execute with Babel. See Configure active languages instructions. Emacs Lisp is activated by default so this step can be skipped for now and all emacs-lisp examples will still work as expected.

  3. If you have made any changes don’t forget to evaluate your modified .emacs.

代码块<a id="source-code-blocks"></a>

代码块在 Org-mode 中<a id="source-code-blocks-org"></a>

Babel 是关于 Org-mode 中代码块的。 如果还不熟悉 Org-mode 中的代码块的概念,请在继续之前查看 Org-mode手册的相关章节

受到支持语言的代码块可以出现在 Org-mode 文件的任意位置。 代码块可以直接在 Org-mode 文件中编辑,但通过 C-c ' 调用的函数 org-edit-src-code 编辑代码往往更容易。 将代码块放全新的缓冲区中,同时激活相应语言的模式,语言的编辑特性你全都可用,真是爽。

#+begin_src language org-switches
,body
#+end_src

ruby 代码的代码块如下所示:

#+begin_src ruby
,require 'date'
,"This file was last evaluated on #{Date.today}"
#+end_src

代码块在 Babel 中<a id="source-code-blocks-babel"></a>

Babel 向代码块添加了一些新的元素。 基本结构变成了:

#+begin_src language  org-switches header-arguments
,body
#+end_src
  • language: 代码块中代码的语言标示。 有效值必须是 org-babel-interpreters 的成员。
  • header-arguments: header-arguments 控制源代码块的执行和输出的许多方面。

请参阅Header Arguments部分,以查看可用的 header-arguments=

  • body: 等待被执行的源代码。 一个重要的键绑定 C-c ' , 调用 org-edit-src-code ,打开一个包含适合于该语言 major mode 的编辑缓冲区。

然后你就可以像往常在emacs编辑代码那样来编辑你的代码块。

源代码执行<a id="source-code-execution"></a>

Babel 通过将代码传递给解释器来执行解释语言(如shell,python,R等)的代码块。 在执行结果上可以做进一步的操作,如果你想的话。

示例<a id="sec-5-1"></a>

以下是三种不同语言的代码块,其后是其输出。 如果正在Emacs中查看本文档的 Org-mode 版本,则把光标放置在块的任何位置,然后按 C-c C-c 执行代码(并随意更改它)。

Ruby<a id="sec-5-1-1"></a>

Org-mode 的文件中:

#+begin_src ruby
require 'date'
"This file was last evaluated on #{Date.today}"
#+end_src

HTML 导出的代码:

require 'date'
"This file was last evaluated on #{Date.today}"

HTML 导出的执行结果:

This file was last evaluated on 2017-04-05

Shell<a id="sec-5-1-2"></a>

Org-mode 的文件中:

#+begin_src sh
  echo "This file takes up `du -h babel-intro.org |sed 's/\([0-9k]*\)[ ]*babel-intro.org/\1/'`"
#+end_src

HTML 导出的代码:

echo "This file takes up `du -h babel-intro.org |sed 's/\([0-9k]*\)[ ]*babel-intro.org/\1/'`"

HTML 导出的执行结构:

This file takes up 36K

R<a id="sec-5-1-3"></a>

当前这个文件中最常用的词是? 在 Org-mode 文件中:

#+begin_src R :colnames yes
  words <- tolower(scan("babel-intro.org", what="", na.strings=c("|",":")))
  t(sort(table(words[nchar(words) > 3]), decreasing=TRUE)[1:10])
#+end_src

HTML 导出的代码:

words <- tolower(scan("babel-intro.org", what="", na.strings=c("|",":")))
t(sort(table(words[nchar(words) > 3]), decreasing=TRUE)[1:10])

ditaa<a id="sec-5-1-4"></a>

Org-mode 文件中:

#+begin_src ditaa :file blue.png :cmdline -r
+---------+
| cBLU    |
|         |
|    +----+
|    |cPNK|
|    |    |
+----+----+
#+end_src

HTML导出的代码: HTML导出的结果图:

捕获代码执行结果<a id="results"></a>

Babel 提供了两种根本不同的模式来捕获代码执行的结果: functional modescripting mode 。 模式的选择可以通过配置 :results 头参数来指定。

:results value (functional mode)<a id="results-value"></a>

代码执行的结果是代码块中最后一个语句的值。 在 functional mode 下,代码块是具有返回值的函数。 一个代码块的返回值可以用作另一代码块的输入,即使是不同语言的输入。 这样的话,Babel成为一种元编程语言。 如果块返回表格数据(某种类型的向量,数组或表),那么将可以作为 Org-mode 的表格保存在缓冲区中。 functional mode 是默认设置。

作为示例,观察以下python代码块及其输出。

import time
print("Hello, today's date is %s" % time.ctime())
print("Two plus two is")
return 2 + 2

请注意,在 functional mode 下,输出只由最后一个语句返回,没有其他情况。

:results output (scripting mode)<a id="results-output"></a>

scripting mode 中,Babel捕获代码块的文本输出并将其放置在 Org-mode 的缓冲区中。 它被称为 scripting mode ,因为代码块包含一系列命令,并返回每个命令的输出。 与功能模式不同,代码块本身除了其包含的命令的输出之外没有返回值。<a id="fnr.2" class="footref" href="#fn.2">2</a>

观察以下使用 scripting mode 执行代码块的结果。

import time
print("Hello, today's date is %s" % time.ctime())
print('Two plus two is')
2 + 2

在这里, scripting mode 返回了python写到 stdout 的文本。 因为代码块不包含最后一个语句 (2 + 2)print() 语句,所以结果中不会出现4。

基于会话的代码块<a id="sec-5-3"></a>

对于某些语言,例如Python,R,ruby和shell,可以在Emacs中运行一个不完备的交互式会话进程。 这意味着创建了一个不同源代码块之间共享数据对象的持久化环境。 Babel 支持使用 :session 头参数来 指定代码块运行于特定会话中。 如果头参数被赋予一个值,那么该参数将被用作会话的名称。 因此,可以并发的在不同的会话中运行同一语言的不同代码块。

基于特定会话的代码块对于原型设计和调试特别有用。 函数 org-babel-pop-to-session 可用于切换会话缓冲区。

一旦代码块编辑完成,通常最好在会话之外执行它,因为这样它执行的环境将是确定的。

With R, the session will be under the control of Emacs Speaks Statistics as usual, and the full power of ESS is thus still available, both in the R session, and when switching to the R code edit buffer with ​C-c '​.

代码块的入参<a id="arguments-to-source-code-blocks"></a>

Babel 支持代码块的参数化,即可以将参数传递给代码块,从而使它们函数化。 functional modescripting mode 都支持入参。

代码块作为函数的简单示例<a id="using-a-code-block-as-a-function"></a>

首先我们来看一个非常简单的例子。 以下源代码块使用Python定义了一个函数,求入参的平方。

return x*x

在 Org-mode 文件中, 函数定义如下:

#+name: square
#+header: :var x=0
#+begin_src python
return x*x
#+end_src

调用函数如下:

#+call: square(x=6,y=8)

(对于 call 语法细节请参阅 Library of Babel)

36

Org-mode 表格作为入参的更复杂的示例<a id="sec-5-4-2"></a>

在本例中,使用Emacs Lisp定义的一个名为 fibonacci-seq 的函数。 函数 fibonacci-seq 计算斐波纳契序列。 该函数只需要一个参数,在当前情况下参数即为 Org-mode 表格的引用。

下面即为传递给 fibonacci-seqOrg-mode 表格:

| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
| 2 | 4 | 6 | 8 | 10 | 12 | 14 | 16 | 18 | 20 |

表格在 Org-mode 的缓冲区中如下所示:

#+tblname: fibonacci-inputs
| 1 | 2 | 3 | 4 |  5 |  6 |  7 |  8 |  9 | 10 |
| 2 | 4 | 6 | 8 | 10 | 12 | 14 | 16 | 18 | 20 |

Emacs Lisp的源代码:

(defun fibonacci (n)
(if (or (= n 0) (= n 1))
    n
  (+ (fibonacci (- n 1)) (fibonacci (- n 2)))))
  (mapcar (lambda (row)
        (mapcar #'fibonacci row)) fib-inputs)

Org-mode 中函数如下所示:

#+name: fibonacci-seq
#+begin_src emacs-lisp :var fib-inputs=fibonacci-inputs
  (defun fibonacci (n)
    (if (or (= n 0) (= n 1))
        n
      (+ (fibonacci (- n 1)) (fibonacci (- n 2)))))

  (mapcar (lambda (row)
            (mapcar #'fibonacci row)) fib-inputs)
#+end_src

fibonacci-seq 的返回值,也是一个表格:

内联(In-line)的代码块<a id="sec-5-5"></a>

可使用以下语法内联(In-line)的执行代码:

Without header args: src_lang{code} or with header args: src_lang[args]{code},
for example src_python[:session]{10*x}, where x is a variable existing in the
python session.

代码如下:

src_python{return "Hello World!"}

执行结果: Hello World!

代码块扩展<a id="sec-5-6"></a>

Babel 在执行之前“扩展”代码块,即,执行代码包括把引用的数据(或代码)填充到代码块内容里。 可以预览展开的内容,还可以在 tangling 期间展开代码。 扩展时,头参数和变量需要一并考虑进去。

  • preview: C-c M-b p (C-c C-v v) 关联到 org-babel-expand-src-block 函数。它可用于在代码块中预览扩展的内容, 对调试很有用。

  • tangling: 扩展的的代码块可以被 tangledtangling 可能包括的变量值

    • 其他代码的执行结果,
    • 存储在标题属性中变量,或者
    • 表格。

tangling 扩展代码块的一个可能用途是用于emacs初始化。 用户名和密码等值可以存储在标题属性或表格中。 可以使用 :no-expand 头参数来阻止 tangling 期间代码块的扩展。

下面是代码块及其生成的扩展的示例。

数据被存储在表格中:

| username | john-doe |
| password | abc123 |

引用数据表格的代码块:

(setq my-special-username (first (first data)))
(setq my-special-password (first (second data)))

在代码块内部, C-c M-b p (C-c C-v v)扩展内容如下:

(let ((data (quote (("john-doe") ("abc123")))))
(setq my-special-username (first (first data)))
(setq my-special-password (first (second data))))

Org-mode 的元编程语言<a id="meta-programming-language"></a>

因为用一种语言编写的函数的返回值可以被传递给另一种语言编写的函数, 或者传递到本身就可程序化的 Org-mode 的表格中, 所以可将 Babel 用作元功能编程语言。 Bable 可使许多语言一起工作, 混合使用各语言,每种语言可用于最合适的任务。

例如,在shell中进行一些系统诊断,并用R图形化诊断结果.

  1. 使用shell代码创建一个代码块,列出program目录中的目录以及它们的大小。Babel自动将输出转换为 Org-mode 表格。

    #+name: directories
    #+begin_src sh :results replace
      cd ~/program/ && du -sc * | grep -v total
    #+end_src
    

    代码如下:

    cd ~/program/ && du -sc * | grep -v total
    

    结果如下:

    #+RESULTS: directories
    |   2392 | github      |
    |  90728 | org         |
    |  15820 | program     |
    | 190488 | program.tgz |
    
  2. 一行R语言编写的函数将 Org-mode 表中的数据绘制为饼形图。 请注意,当前代码块如何使用前一代码块的 srcname 来获取的数据

    Org-mode 文件中:

    #+name: directory-pie-chart(dirs = directories)
    #+begin_src R :session R-pie-example :file ../images/babel/dirs.png :var dirs=directories() :results graphics
      pie(dirs[,1], labels = dirs[,2])
    #+end_src
    

    注: :results graphics 请参阅 Org Mode Features for R Source Code Blocks

    HTML 导出的代码:

    pie(dirs[,1],labels=dirs[,2])
    

在Org表格中使用代码块<a id="spreadsheet"></a>

除了可将表格中的数据作为参数传递给代码块和结果存储为表格外, Babel 还有第三种方式使用 Org-mode 表格。 Org-mode 现有电子表格 功能允许使用 #+TBLFM 从指定单元格值自动计算出其他单元格值。 通过以上方式,表可使用calc emacs lisp来执行计算任务。

Babel 有效扩展了 #+TBLFM 行使用代码块(以任何语言)进行必要计算的能力。

示例<a id="sec-6-1"></a>

示例 1: 使用R生成数据概要<a id="sec-6-1-1"></a>

将使用几个数字的平均值来填充 Org-mode 表中的一个单元格,来做简单示例。 首先,要生成数据, 以下代码块生成0和1之间的五个随机数来填充了 Org-mode 表。

Org-mode 文件中,如下所示:

#+name: tbl-example-data
#+begin_src R
runif(n=5, min=0, max=1)
#+end_src

HTML 导出的代码如下:

runif(n=5, min=0, max=1)

紧接着定义一个代码块计算来表列的平均值。

Org-mode 文件中,如下所示:

#+name: R-mean
#+begin_src R :var x=""
colMeans(x)
#+end_src

HTML 导出的代码如下:

colMeans(x)

最后,创建使用R代码的表。 通过使用 org-sbe (’source block evaluate’)宏来完成的代码块的调用。

Org-mode 文件中,表格调用代码块如下所示:

#+tblname: summaries
|              mean |
|-------------------|
| 0.779619386699051 |
#+TBLFM: @2$1='(org-sbe "R-mean" (x "tbl-example-data()"))

HTML export of code:

mean
0.58

重新计算表格公式,请在表格中使用 C-u C-c C-c 。 每次重新计算表格公式时,代码块都会再次计算,因此计算的平均值会发生变化。

示例 2: Babel 的测试套件<a id="sec-6-1-2"></a>

While developing Babel, we used a suite of tests implemented as a large Org-mode table.

在开发 Babel 时,开发者曾使用了一个居大的 Org-mode 表作为测试套件。 要运行测试套件,我们只需使用 C-u C-c C-c 对表进行计算:运行所有测试,将结果与期望进行比较,并使用结果和通过/失败的状态信息来更新表。

测试套件的简单版本如下.

Org-mode 文件中,如下所示:

#+TBLNAME: org-babel-tests
| functionality    | block        | arg |    expected |     results | pass |
|------------------+--------------+-----+-------------+-------------+------|
| basic evaluation |              |     |             |             | pass |
|------------------+--------------+-----+-------------+-------------+------|
| emacs lisp       | basic-elisp  |   2 |           4 |           4 | pass |
| shell            | basic-shell  |     |           6 |           6 | pass |
| ruby             | basic-ruby   |     |   org-babel |   org-babel | pass |
| python           | basic-python |     | hello world | hello world | pass |
| R                | basic-R      |     |          13 |          13 | pass |
#+TBLFM: $5='(if (= (length $3) 1) (org-sbe $2 (n $3)) (org-sbe $2)) :: $6='(if (string= $4 $5) "pass" (format "expected %S but was %S" $4 $5))

HTML 导出的代码:

functionality block arg expected results pass
basic evaluation pass
emacs lisp basic-elisp 2 4 4 pass
shell basic-shell 6 6 pass
ruby basic-ruby org-babel org-babel pass
python basic-python hello world hello world pass
R basic-R 13 13 pass
  1. 用于测试的代码块

    Org-mode 文件中,如下所示::

    #+name: basic-elisp
    #+begin_src emacs-lisp :var n=0
    (* 2 n)
    #+end_src
    

    HTML 导出代码,如下所示::

    (* 2 n)
    

    Org-mode 文件中,如下所示::

    #+name: basic-shell
    #+begin_src sh :results silent
    expr 1 + 5
    #+end_src
    

    HTML 导出代码,如下所示::

    expr 1 + 5
    

    Org-mode 文件中,如下所示::

    #+name: date-simple
    #+begin_src sh :results silent
    date
    #+end_src
    

    HTML 导出代码,如下所示::

    date
    

    Org-mode 文件中,如下所示::

    #+name: basic-ruby
    #+begin_src ruby :results silent
    "org-babel"
    #+end_src
    

    HTML 导出代码,如下所示::

    "org-babel"
    

    Org-mode 文件中,如下所示:

    #+name: basic-python
    #+begin_src python :results silent
    "hello world"
    #+end_src
    

    HTML 导出代码,如下所示::

    return "hello world"
    

    Org-mode 文件中,如下所示::

    #+name: basic-R
    #+begin_src R :results silent
    b <- 9
    b + 4
    #+end_src
    

    HTML 导出代码,如下所示::

    b <- 9
    b + 4
    

Babel库文件<a id="library-of-babel"></a>

(可参阅 Org manual:Library-of-Babel)

正如上面的 square 示例中看到的,一旦代码块被定义,可使用 lob 符号反复调用:

#+lob: square(x=6)

但是,若是需要为每个 Org-mode 缓冲区提供的通用,可重用的代码块呢?

除了当前的缓冲区外, Babel 还会搜索 *Babel*库文件中预先定义的代码块。 这是一个用户可扩展的现成的代码块集合,用于处理常见任务。 对于 Bable 库(尚未完成!)的一个可能的用途就是是使用R,gnuplot,asymptote等语言为 Org-mode 表中保存的数据提供绘图功能。 如果你定义的某些代码块 对其他 Org-mode 用户也非常有用,可考虑将其添加到 Babel 库中; 类似的,可以随时求助,*Babel* 可引用外部代码来解决问题 – 其他Babel用户也有机会提供一些有用的代码。

Babel预先填充(即把库中的代码块加载到缓冲区中)位于 Babel库文件 中的代码块 - library-of-babel.org 上的原始文件。 可使用 org-babel-lob-ingest (绑定到 C-c C-v i )从任何 Org-mode 文件中向库添加代码块。

(org-babel-lob-ingest "path/to/file.org")

注: 可以将表值或源代码块的输出传递给 Babel 库函数。 还可以在代码块的参数中引用 Babel 函数库函数。

文学化编程<a id="literate-programming"></a>

Let us change our traditional attitude to the construction of programs: Instead of imagining that our main task is to instruct a computer what to do, let us concentrate rather on explaining to human beings what we want a computer to do.

让我们改改传统上构建程序的态度:不要认为程序的主要任务是指导计算机怎么做,相反,程序要致力于向人们解释,它想让计算机做什么。<a id="fnr.3" class="footref" href="#fn.3">3</a>

The practitioner of literate programming can be regarded as an essayist, whose main concern is with exposition and excellence of style. Such an author, with thesaurus in hand, chooses the names of variables carefully and explains what each variable means. He or she strives for a program that is comprehensible because its concepts have been introduced in an order that is best for human understanding, using a mixture of formal and informal methods that reinforce each other.

文学编程人士可被视为作家,他们首要考虑的任务是如何清楚地阐述、如何形成优秀的风格。 这样的作者胸有成竹,会仔细地挑选变量名,并给予解释。为力求程序之可读, 他/她使用形式和非形式互补的混合手法,将各种概念按照人们能理解的方式顺序编排下来。<a id="fnr.3.100" class="footref" href="#fn.3">3</a> – Donald Knuth

Babel支持 文学编程 (LP),允许编程行为发生在 Org-mode 文档中。 然后可将 Org-mode 文件导出(用LP语言编写)到HTML或LaTeX等更可视化的文本格式中以供人类查阅和使用, 并且可以将嵌入的源代码( tangle in LP speak)转换成源代码文件以供计算机执行。

为了支持这些操作, Babel 依赖于 Org-mode文档的导出功能 来编排文档, 依赖于使用 Noweb reference syntax tangling 代码文件的 org-babel-tangleC-c C-v t ) 函数。

以下示例演示了在 Babeltangling 的过程。

tangling 的示例<a id="sec-8-1"></a>

简单文学编程示例 (Noweb syntax)<a id="literate-programming-example"></a>

Tangling functionality is controlled by the tangle family of tangle header arguments. These arguments can be used to turn tangling on or off (the default), either for the code block or the Org-mode heading level.

以下代码块演示如何使用 org-babel-tangleC-c C-v t ) 把分散的代码块 tangle 为单个源代码文件。

以下两个代码块没有 tangle 头参数,因此不会创建源代码文件。 它们通过第三个代码块被包含在源代码文件中,该代码块具有 tangle 头参数。

Org-mode 文件中,如下所示::

#+name: hello-world-prefix
#+begin_src sh :exports none
  echo "/-----------------------------------------------------------\\"
#+end_src

Org-mode 文件中,如下所示:

#+name: hello-world-postfix
#+begin_src sh :exports none
  echo "\-----------------------------------------------------------/"
#+end_src

第三个代码块具有 tangle 头参数,指出将被写入的源代码的文件的名称。 它还包含了前面两个代码块的Noweb样式引用。 这些引用将在 tangling 期间扩展,以使它们包含在输出文件中。

Org-mode 文件中,如下所示::

#+name: hello-world
#+begin_src sh :tangle hello.sh :exports none :noweb yes
  <<hello-world-prefix>>
  echo "|                       hello world                         |"
  <<hello-world-postfix>>
#+end_src

调用函数 org-babel-tangleC-c C-v t )将shell源码写到 hello.sh 文件中:

#!/usr/bin/env sh
echo "/-----------------------------------------------------------\\"
echo "|                       hello world                         |"
echo "\-----------------------------------------------------------/"

此外,可以使用以下语法来插入代码块执行的结果,在下面情况下是名为 example-block 的代码块的执行结果。

<< example-block() >>

任何可选参数都可以传递给 example-block() ,方法是将参数放入括号内,并遵循调用代码块函数定义的约定(参见 babel库)。 如下:

<< example-block(a=9) >>

参数 “a” 的值设置为等于 “9”。 请注意,这些参数不在当前源代码块中执行,而是按字面顺序传递给 example-block()

用Bable初始化Emacs<a id="emacs-initialization"></a>

Babel 对于将Emacs初始化信息嵌入 Org-mode 文件中有特别的支持。 org-babel-load-file 函数可用于加载嵌入在 Org-mode 文件中的Emacs Lisp代码块,方法与加载常规Emacs Lisp文件(如.emacs)相同。

这就允许利用Org-mode的功能特性,例如折叠,标签,笔记,HTML导出等,来组织和维护Emacs初始化配置。

要想了解这一点,可以参考简单的优雅的Emacs初始化示例,或者查看 Org-babel-emacs-starter-kit 中提供的 Phil Hagelberg 的优秀 emacs-starter-kitBabel Literate Programming 版本。 To try this out, either see the simple Literate Emacs Initialization example, or check out the Babel Literate Programming version of Phil Hagelberg’s excellent emacs-starter-kit available at Org-babel-emacs-starter-kit.

  1. 优雅的Emacs初始化

    请按照以下5个步骤进行操作:

    1. 在主目录的内创建一个名为 .emacs.d 的目录;

      mkdir ~/.emacs.d
      
    2. checkout 最新版本的 Org-mode 到这个新目录的src子目录中; of this new directory;

      cd ~/.emacs.d
      mkdir src
      cd src
      git clone git://orgmode.org/org-mode.git
      
    3. 将以下代码块放入Emacs初始化目录( ~/.emacs.d )下名为 init.el 的文件中。

      ;;; init.el --- Where all the magic begins
      ;;
      ;; This file loads Org-mode and then loads the rest of our Emacs initialization from Emacs lisp
      ;; embedded in literate Org-mode files.
      
      ;; Load up Org Mode and (now included) Org Babel for elisp embedded in Org Mode files
      (setq dotfiles-dir (file-name-directory (or (buffer-file-name) load-file-name)))
      
      (let* ((org-dir (expand-file-name
                       "lisp" (expand-file-name
                               "org" (expand-file-name
                                      "src" dotfiles-dir))))
             (org-contrib-dir (expand-file-name
                               "lisp" (expand-file-name
                                       "contrib" (expand-file-name
                                                  ".." org-dir))))
             (load-path (append (list org-dir org-contrib-dir)
                                (or load-path nil))))
        ;; load up Org-mode and Org-babel
        (require 'org-install)
        (require 'ob-tangle))
      
      ;; load up all literate org-mode files in this directory
      (mapc #'org-babel-load-file (directory-files dotfiles-dir t "\\.org$"))
      
      ;;; init.el ends here
      
    4. 在Emacs Lisp代码块中实现所有Emacs定制,嵌入在该目录中的 Org-mode 文件中; 和

    5. 重启Emacs读取自定义配置。

可重复性研究<a id="reproducable-research"></a>

An article about computational science in a scientific publication is not the scholarship itself, it is merely advertising of the scholarship. The actual scholarship is the complete software development environment and the complete set of instructions which generated the figures.

– D. Donoho

可重复性研究 (RR)是与科研出版物一起分发的所有数据,软件源代码和重现出版物中讨论的结果所需的工具的方法。 因此,RR包不仅描述了研究及其结果,而且成为可以复制和扩展研究的完整实验室。

Org-mode 已经很好的支持导出到HTML和LaTeXBabel 通过激活嵌入在 Org-mode 文档中的数据和代码块,使组织模式成为RR的工具; 整个文档变得可执行。 这使得鼓励读者重新创建结果并实验自己的思路来分发科研成果成为可能。

Sweave 是目前比较知名的RR工具,它提供了将R代码嵌入到LaTeX文档中的机制。 Sweave是一个成熟而且非常有用的工具,但我们认为 Babel 有几个优点:

  • 支持多种语言
  • 导出过程灵活强大,除了LaTeX之外,还包括HTML作为目标格式; 和
  • 文档可利用 Org-mode 强大的功能特性,支持项目规划和任务管理等。

推荐阅读更多精彩内容