Skip to content

Latest commit

 

History

History
1499 lines (1125 loc) · 66.4 KB

org笔记.org

File metadata and controls

1499 lines (1125 loc) · 66.4 KB

标题

视图循环

  1. TAB 子树循环:当加上一个前缀参数时(C-u TAB),在下面的状态中改变当前子树的视图
  2. S+TAB 全局视图循环
  3. C-u C-u C-u TAB 显示全部

移动

  1. C-c C-n 下个标题
  2. C-c C-p 上个标题
  3. C-c C-f 下个同级的标题
  4. C-c C-b 上个同级的标题
  5. C-c C-u 回到上层标题

结构编辑

  1. M-RET 插入一个同级标题。如果光标在文本列表中,创建一个新的项。如果处于一行的中间,这一行会被分开,后面的一部分成为新的标题。
  2. C-RET 与 M-RET 类似,但如果处于一行的中间,不会把后面的内容作为标题
  3. M-S-RET 插入一个和当前标题同级的 TODO 项
  4. C-S-RET 与 M-S-RET 类似
  5. TAB(新的空的条目中) 如果新的条目中还没有文字,TAB 可以调整级别。
  6. M-LEFT/RIGHT 将当前的标题提升/降低一个等级。
  7. M-S-LEFT/RIGHT 将当前子提升/降低一个等级。
  8. M-S-UP/DOWN 将子树上/下移(和前/后个子树交换)。
  9. C-c C-w 将条目或区域重新归档到其他位置。
  10. C-x n s 和 C-x n w 将缓冲区视图局限到当前子树中/再次放宽视图

Sparse 树

Org 模式的一个重要的功能是能根据大纲树中选择的信息构造出稀疏的树,这样文档就可以尽可能地折叠,但是选择的信息和它对应的标题会显示出来。试下就知道它是怎样工作的了。

Org 模式有几个命令可以创建这种树,这些命令都可以通过调度器来使用:

  • C-c / 它会提示再输入一个字符来选择稀疏树的创建命令。
  • C-c / r 触发后,会提示输入匹配串,并且将所有匹配的项显示成稀疏树。所有的匹配项都会高亮显示;按 C-c C-c 取消高亮。

文字强调

You can make words ‘*bold*’, ‘/italic/’, ‘_underlined_’, ‘=verbatim=’ and ‘~code~’, and, if you must, ‘+strike-through+’.

自定义设置

;;关闭所有文字强调功能
(setq org-fontify-emphasized-text nil)

对变量 org-emphasis-alist 进行设置可以自定义修改强调方式

列表

无序列表项以 -、+或者*开头。

有序列表项以 1.、1)或者开头。

描述列表用::将项和描述分开。

同一列表中的项的第一行必须缩进相同程度

  1. TAB 折叠项
  2. M-RET 在当前级别插入一个项,有前缀时是强制新建一个标题
  3. M-S-RET 插入一个带有复先框的项(见 2.5 节[复先框])
  4. M-S-UP/DOWN 将当前项和它的子项向上/下移动(和相同的缩进的前/后一个项交换位置)。如果列表是有序的,数字会自动改变
  5. M-LEFT/M-RIGHT 提升/降低项的缩进,不包含子项
  6. M-S-LEFT/RIGHT 提升/降低项的缩进,包含子项
  7. C-c C-c 如果项中有复先框,就触发改变其状态。并且自动保持本项的符号与缩进在列表中的一致性
  8. C-c - 循环改变将当前列表的项标志符号

在 Org-mode 中重置有序列表序号可以直接使用 M-<RET> 。

脚注

脚注就是以脚注定义符号开头的一段话,脚注定义符号是将脚注名称放在一个方括号里形成的,要求放在第 0 列,不能有缩进。而引用就是在正文中将脚注名称用方括号括起来。例如:

The Org homepage[fn:1] now looks a lot better than it used to. … [fn:1] The link is: http://orgmode.org

注脚命令:

  • C-c C-x f 当光标位于注脚引用处,该命令会跳转到注脚定义处. 若光标处于注脚定义处,跳转到(第一个)引用处.否则,创建一个新的注脚.
  • C-c C-c 当光标位于注脚引用处时,跳转到注脚定义处. 若光标处于注脚定义处,则跳转回注脚引用处. 若在标注位置上用带前置参数的方式调用该命令,则弹出一个与 C-c C-x f 一样的菜单.
  • C-c C-o 不知道是啥

表格

  • C-c C-c 调整表格,不移动光标
  • TAB 调整表格,将光标移到下一个区域,必要时新建一行
  • S-TAB 调整表格,将光标移到上一个区域
  • RET 调整表格,将光标移到下一行,必要时会新建一行
  • M-LEFT/RIGHT 左/右移当前列
  • M-S-LEFT 删除当前行
  • M-S-RIGHT 在光标位置左边添加一列
  • M-UP/DOWN 上/下移当前行
  • M-S-UP 删除当前行
  • M-S-DOWN 在当前行上面添加一行。如果有前缀,则在下面添加一行
  • C-c - 在当前行下面添加一个水平线。如果带前缀,则在上面添加一行水平线
  • C-c RET 在当前行下面添加一个水平线。并将光标移动到下一行
  • C-c ^ 将表排序。当前位置所在的列作为排序的依据。排序在距当前位置最近的两个水平线之间的行(或者整个表)中进行

表格的创建

使用|创建

创建表格的方法

|Name|Phone|Age|
|-

然后按 TAB,或者输入|Name|Phone|Age|后按 C-c RET

C-c | 将活动区域(选中区域)转换成一个表。

如果第一行至少有一个 TAB 字符,就用 TAB 划分内容;

如果第一行都有逗号,就分逗号划分内容;

否则就用空白符来划分区域。如果当前没有活动区域就会建立一个空的 Org 表格。

快捷键 C-c -

|Name|Phone|Age|

然后按下 C-c -即可自动创建表格

快捷键 C-c |

快速创建指定大小的表格。使用这个快捷键后,会提示输入创建的表格的大小,默认是 5x2 也就是 5 列 2 行的,且其中一行是 header.

由选中内容创建表格

可将 buffer 上已有的数据格式化成表格,比如如果是以逗号(,)分隔的 CSV 格式的数据,可以将其拷贝到当前在编辑的 Org mode 文档中,选中,然后使用 “C-c |” 这个快捷键,就能将其转换成表格形式.

org-table-import

Org mode 提供了 “org-table-import” 这个命令来将外部文件导入到 Org mode 文档中并用它来创建表格, 与之对应的,命令 “org-table-export” 则能将 Org mode 文档中的表格导出成文件。 文件格式可以是 CSV 的,也可以是以制表符(TAB)或空白字符作为分隔符的。

表格公式

Org mode 中的表格的另外一个强大之处,在于它支持公式。 在表格区域使用快捷键 “C-c ‘”,就可以对表格公式进行编辑,完成后公式会显示在表格下方,以 “#+TBLFM:” 开头 我们也可以在表格下方手工添加以 “+TBLFM:” 开头的行,然后直接添加公式。

表格单价数量花费
苹果2.838.4
香蕉428
柚子5420
橘子339

上面这个公式表示将第四列的值设为第二列的值与第三列的值的乘积。 在编辑好公式并保存后,将光标移动到公式所在行然后使用 “C-c C-c”,就可以应用公式到表格中。

在 Org mode 的表格公式中,用 “@” 来表示行,用 “$” 来表示列,最简单的,”@3$2” 表示的是第三行第二列的位置。 使用快捷键 “C-c }” 可以开启表格的横纵坐标显示——若要关闭的话也是用它。如果是用 “C-c ‘” 来进行公式编辑,在输入表格位置时,会看到表格上对应的位置会在当时高亮,所以建议用这种方式进行编辑。

如果只给一个坐标,则另一个坐标会被设为”当前行”或者”当前列”,这在批量处理表格内容时会有用。

如果想表示一个区域的话,用 “..” 来表示。

下面这个表示左上角为第二行第一列单元格、右下角为第四行第三列单元格的区域,共包含 9 个单元格。 @2$1..@4$3

下面这个则表示”当前行”的第一列到第三列的区域: $1..$3

在公式中,可以用 “@#” 表示当前行的行号,用 “$#” 表示当前列的列号,在一些稍复杂点的公式里会有用。

此外,还可以定义常量、变量,或者给某个单元格命名,然后引用它们。假设其名字为 “name”,那么 “$name” 就可以引用它了。常量的定义可以通过 “org-table-formula-constants” 来进行,这样定义的常量是全局的;如果要定义局部的常量,可以在 org 文件中添加诸如这样的行:

还可以在当前表格引用其他表格的域,这需要其他表格被命名为某个名字,如”FOO”,我们要在另一个表格中使用其第三行第四列的域,将其值赋给当前表格的第五行第二列,则可以这样写:

@5$2=remote(FOO, @3$4)

超链接

[[link][description]]  或者  [[link]]

内部链接

如果一个链接地址并不是 URL 的形式,就会作为当前文件内部链接来处理。

[[#my-custom-id]] #链接到 CUSTOM_ID 属性是 “my-custom-id” 的项。

[[My Target]] [[My Target][Find my target]] #点击后本文件中查找对应的目标 “<<My Target>>” 

外部链接

Org 支持的链接格式包括文件、网页、新闻组、BBDB 数据库项、IRC 会话和记录。

http://www.astro.uva.nl/~dominik            on the web
file:/home/dominik/images/jupiter.jpg       file, absolute path
/home/dominik/images/jupiter.jpg            same as above
file:papers/last.pdf                        file, relative path
file:projects.org                           another Org file
docview:papers/last.pdf::NNN                open file in doc-view mode at page NNN
id:B7423F4D-2E8A-471B-8810-C40F074717E9     Link to heading by ID
news:comp.emacs                             Usenet link
mailto:[email protected]                     Mail link
vm:folder                                   VM folder link
vm:folder#id                                VM message link
wl:folder#id                                WANDERLUST message link
mhe:folder#id                               MH-E message link
rmail:folder#id                             RMAIL message link
gnus:group#id                               Gnus article link
bbdb:R.*Stallman                            BBDB link (with regexp)
irc:/irc.com/#emacs/bob                     IRC link
info:org:External%20links                   Info node link (with encoded space)

目标链接

文件链接可以包含一些其他信息使得进入链接时可以到达特定的位置。比如双冒号之后的一个行号或者搜索选项。

下面是一些包含搜索定位功能的链接例子以及其说明:

file:~/code/main.c::255                     进入到 255 行
file:~/xx.org::My Target                    找到目标‘<<My Target>>’
file:~/xx.org/::#my-custom-id               查找自定义 id 的项

快捷键

  • C-c l 在当前位置保存一个链接。这是一个全局命令(你可以设置自己的快捷键),可以在任何类型的缓冲区中使用。链接保存下来以便以后插入 Org 文件中。
  • C-c C-l 插入一个链接。它会让你输入,你可以输入一个链接,也可心用上/下键来获取保存的链接。它还会让你输入描述信息。
  • C-c C-l (光标在链接上) 当光标处于链接上时,你可以修改链接
  • C-c C-o 或者 mouse-1 或者 mouse-2 打开链接
  • C-c & 跳回到一个已记录的地址。用 C-c % 可以将地址记录下来,内部链接后面的命令也会自动将地址记录下来。使用这个命令多次可以一直往前定位。

关于插入图片的方法

  1. 使用系统自带方法
  2. org-download 插件

org-download 本身会自动在 org 文档当前目录下创建一个与文档同名的文件夹来保存图片,然后支持多种途径的图片插入,插入之后会复制或者下载一张图片到图片文件夹下面:

  • 用 url 把图片插入,然后自动下载;
  • 复制图片文件路径,然后插入;
  • 拖拽图片插入。

但是,org-download 不会把剪切板中的图片自动保存一个图片文件,然后插入。所以,必须要借助于外部程序。可以使用任意一个带命令行参数的图片保存器将剪切板中的图片进行保存。有人写了一个 csharp 的程序,很小很小就可以做到了。我这里直接使用 ImageMagick ,因为这个软件实在是太强大了,而且是免费的。路径我们可以根据自己的安装路径来进行配置,然后,先调用里面的 convert.exe 把剪切板里面的图片保存到一个临时目录下面。我这里是 d:/temp/ ,这个可以根据自己的需要来设置。然后,定义了一个快捷键 C-S-Y ,比原来的粘贴键多了一个 shift,就可以粘贴图片了。

截图软件:剪切板中的图片可以是从另外一个地方复制来的,但更多的场景是使用截图软件进行截图,然后粘贴的。我使用的截图软件是 faststone,程序很小,但是功能很强大,既可以截图也可以录视频,还可以编辑视频,对于简单的插入便条,字幕之类的处理,特别方便。还可以设置快捷键,截选择框、窗口、滚动条内窗口内容等等,非常方便。

待办事项

Org 模式并不用一个单独的文件来维持 TODO 列表。它是一些笔记的集合体,因为 TODO 列表是在你记录笔记的过程中逐渐形成的。你 Org 模式下可以很容易地将树中的一项标记为一个 TODO 的项。用这种方式,信息内容不会冗余加倍,而且可以显示 TODO 项的上下文环境。

当然,这种处理待办事项的方式会将它们分散于各个笔记文件中。Org 模式提供了一些方法使我们可以把它们看作一个整体来处理。

使用 TODO 状态

当标题以 TODO 开头时就成为一个 TODO 项

#*** TODO 标题

注意空格位置。

改变 TODO 的状态会触发标签改变。查看选项 org-todo-state-tags-triggers 的描述获得更多信息

  • C-c C-t 将当前项的状态在(unmarked)->TODO->DONE 之间循环切换,同样的切换也可以在时间轴(timeline) 和议程( agenda) 的缓冲区(buffer)中用 t 键“远程”进行。
  • S-RIGHT/LEFT 选择下一个/上一个 TODO 状态,与上面的循环方式相同。
  • C-c / t 在稀疏树中显示 TODO 项。将 buffer 折叠,但是会显示 TODO 项和它们所在的层次的标题。
  • C-c a t 显示全局 TODO 列表。从所有的议程文件中收集 TODO 项到一个缓冲区中。详见 10.3.2 节。
  • S-M-RET 在当前项下插入一个新的 TODO 项。

多状态工作流

你可以用 TODO 关键字来定义不同的状态,用以处理项,比如:

(setq org-todo-keywords
      '((sequence "TODO" "FEEDBACK" "VERIFY" "|" "DONE" "DELEGATED")))

竖直线将 TODO 关键字(还需要进一步的动作)和 DONE 状态(不需要进一步的动作)分隔开。

如果你不给出竖直线,最后一个状态会作为 DONE 状态。

设置之后,C-c C-t 就会将状态从 TODO 转换到 FEEDBACK,再转换到 VERIFY,最后到 DONE 和 DELEGATED。

有时你可能希望同时使用几个不同的 TODO 状态集合。例如,你可能想要一个基本的 TODO/DONE,以及一个修改 bug 的工作流程和一个隔开的状态来表示取消的项目(既还是 DONE,也不需要进一步的动作),你可以这样设置:

(setq org-todo-keywords
      '((sequence "TODO(t)" "|" "DONE(d)")
        (sequence "REPORT(r)" "BUG(b)" "KNOWNCAUSE(k)" "|" "FIXED(f)")
        (sequence "|" "CANCELED(c)")))

关键字应该各不相同,这样对于一个选项 Org 才知道该用哪个状态序列(集合)。

例子中也给出了快速使用一个关键字的方法,就是在关键字后面括号中给出快捷字母——当用 C-c C-t 时,会询问,让你输入一个字母。

要定义只在一个文件中有效的 TODO 关键字,可以在文件中任意地方给出下面的文本:

#+TODO: TODO(t) | DONE(d)
#+TODO: REPORT(r) BUG(b) KNOWNCAUSE(k) | FIXED(f)
#+TODO: | CANCELED(c)

当改变这些行中的一行后,光标停留在改变行上,用 C-c C-c 让改变生效。

进度日志

当你改变一个 TODO 状态为 DONE 时,或者当你每次改变一个 TODO 项的状态时,Org 都会自动记录时间戳或者作一个记录。这是高度可配置的。可以基于每一个关键字进入设置,并且可以定位到一个文件甚至子树。

完成的项目

最基本的日志功能是跟踪一个特定项目的完成。这可以这样实现:

(setq org-log-done 'time)

这时当你将一个项目从一个 TODO(未完成)状态改变为一个完成状态时,标题下面就会插入一行 “CLOSED:[timestamp]”。如果你想和时间戳一起作一个记录,用:

(setq org-log-done 'note)

这时会提示你输入一个记录(note),并将它保存在标题为“Closing Note”项目之下。

跟踪 TODO 状态变化

你可能想跟踪 TODO 状态的变化。可以只记录一个时间戳,也可以为变化作一个带时间戳的记录。记录会被插入到标题之后形成列表。当有很多记录之后,你可能希望将记录取出放到抽屉里。通过定制变量 org-log-into-drawer 可以实现这个功能。 对于状态记录,Org 可以实现基于每个状态关键字的设置。实现方法是在每个后的括号中指定“!”(记录时间戳)或“@”(作一个记录)。例如:

#+TODO: TODO(t) WAIT(w@/!) | DONE(d!) CANCELED(c@)

将会设置 TODO 关键字和快速访问字母,以及当一个项目设为 DONE 时,会记录时间戳,当状态变为 WAIT 或 CANCELED 时,会作一个记录。这个语法也适用于变量 org-todo-keywords。

优先级

Org 模式支持三个优先级别:A、B和 C。

A 是最高级别,如不指定,B是默认的。

优先级只在议程中有用。

  • C-c , 设置当前标题的优先级。按 a,b,c 选择一个级别,或者 SPC 删除标记(cookie)。
  • S-UP , S-Down 增加/减少当前标题的优先级。

任务细分

你可以在标题的任何地方插入[/]或者[%]。

当每个子任务的状态变化时,或者当你在标记上按 C-c C-c 时,这些标记状态也会随之更新。

* Organize Party [33%]
** TODO Call people [1/2]
*** TODO Peter
*** DONE Sarah
** TODO Buy food
** DONE Talk to neighbor

复选框

当纯文本中的项以‘[]’开头时,就会变成一个复选框。

复选框不会包含在全局 TODO 列表中,所以它们很适合地将一个任务划分成几个简单的步骤。

下面是一个复选框的例子:

#* TODO Organize party [1/3]
#  - [-] call people [1/2]
#    - [ ] Peter
#    - [X] Sarah
#  - [X] order food
#  - [ ] think about what music to play

复选框是分层工作的。所以如果一个复选框项目如果还有子复选框,触发子复选框将会使该复选框变化以反映出一个、多个还是没有子复选框被选中。

  • C-c C-c 触发复选框的状态或者(加上前缀)触发复选框的的存在状态。
  • M-S-RET 增加一个带有复选框的项。这只在光标处于纯文本列表

标签

要为交叉相关的信息提供标签和上下文,一个不错的方法是给标题分配标签。Org 模式能够广泛地支持标签。

每一个标题都能包含多个标签,它们位于标题的后面。标签可以包含字母,数字, ‘_’‘@’ 。标签的前面和后面都应该有一个冒号,例如,“:work:”。可以指定多个标签,就像“:work:urgent:”。标签默认是粗体,并和标题具有相同的颜色。

标签继承

标签具有大纲树的继承结构。如果一个标题具有某个标签,它的所有子标题也会继承这个标签。例如,在列表

* Meeting with the French group     :work:
** Summary by Frank                 :boss:notes:
*** TODO Prepare slides for him     :action:

中,尽管没有明确标出,最后一个标题会有标签“:work:”,“:boss:”,“:note:”,和“:action”。你也可以设定一个标签让所有的标题都继承,就好像标签在包含整个文件的第零级标题中指定了一样。用下面的方法[fn:8]:

#+FILETAGS: :Peter:Boss:Secret:

设置标签

在标题后可以很容易地输入标签。在冒号之后,M-TAB 可以补全标签。也有一些专门的命令用于输入标签:

Org 支持基于一个标签列表来插入标签。默认情况这个列表是动态构建的,包含了当前缓冲区中使用过的所有标签。你也可以通过变量 org-tag-alist 在全局设定一个标签的硬列表(hard list)。另外,对于某个特定文件你也可以用下面这几行设置一个默认列表:

C-c C-q为当前标题输入标签。Org 模式既支持补全,也支持单键接口来设置标签,见下文。回车之后,标签会被插入,并放到第 org-tags-column 列。如果用前缀 C-u,会把当前缓冲区中的所有标签都对齐到那一列,这看起来很酷。
C-c C-c当光标处于标题上时,这个命令同 C-c C-q。
#+TAGS: @work @home @tennisclub
#+TAGS: laptop car pc sailboat

默认 Org 模式用一个迷你缓冲区补全设施来输入标签。另外,它也实现了一个更快速,称为 快速标签选择fast tag selection )的标签选择方法。这使得你只用按一次键就可以选择或者取消一个标签。为了使它能很好地工作,需要为常用的标签赋唯一的值。你可以在你的“.emacs”文件中通过设置变量 org-tag-alist 作全局设定。例如,如果你需要在不同的文件中经常要给条目添加标签“:@home:”,这时你就可以像这样设置:

(setq org-tag-alist '(("@work" . ?w) ("@home" . ?h) ("laptop" . ?l)))

如果标签只用于当前正在处理的文件,那么你可以这样设置标签选项行:

#+TAGS: @work(w) @home(h) @tennisclub(t) laptop(l) pc(p)

标签查找

一旦标签体系设置好,就可以用来收集相关联的信息到指定列表中。

这些命令都会提示输入字符串,字符串支持基本的逻辑去处。像“+boss+urgent-project1”,是搜索所有的包含标签“boss”和“urgent”但不含“project1”的项;而 “Kathy|Sally”,搜索标签包含“Kathy”或者“Sally”和项。搜索字符串的语法很丰富,支持查找 TODO 关键字、条目级别和属性。更详细的介绍和例子,见第 10.3.3 节。

C-c \
C-c / m用匹配标签搜索的所有标题构造一个稀疏树。带前缀参数 C-u 时,忽略所有还是 TODO 行的标题。
C-c a m用所有议程文件匹配的标签构造一个全局列表。见第 10.3.3 节。
C-c a M用所有议程文件匹配的标签构造一个全局列表,但只搜索 TODO 项,并强制搜索所有子项(见变量 org-tags-match-listsublevels)。

扩展阅读
手册第 6 章\ Sacha Chua’s article about tagging in Org-mode

属性

属性是一些与条目关联的键值对。它们位于一个名为 PROPERTIES 的特殊抽屉中。第一个属性都单独一行,键在前(被冒号包围),值在后:

* CD collection
** Classic
*** Goldberg Variations
,    :PROPERTIES:
,    :Title:    Goldberg Variations
,    :Composer: J.S. Bach
,    :Publisher: Deutsche Grammophon
,    :NDisks:   1
,    :END:

通过设置属性 “:Xyz_ALL:” ,你可以为属性 “:Xyz:” 设置所有合法的值。这个特定的属性是有 继承性 的,即,如果你是在第 1 级别设置的,那么会被应用于整个树。当合法的值设定之后,设置对应的属性就很容易了,并且不容易出现打字错误。用 CD 唱片集为例,我们可以预定义发行商和盒中的光盘数目:

* CD collection
,  :PROPERTIES:
,  :NDisks_ALL: 1 2 3 4
,  :Publisher_ALL: "Deutsche Grammophon" Philips EMI
,  :END:

也可以在全局设置 org-global-properties ,或者在文件级别设置:

#+PROPERTY: NDisks_ALL 1 2 3 4

要基于选择的属性创建稀疏树或者特殊列表,跟标签搜索的命令相同(见第 6.3 节)。搜索字符串的语法在第 10.3.3 节中详述。

C-c C-x p设置一个属性。会询问属性名和属性值。
C-c C-c d从当前项中删除一个属性。

扩展阅读

手册第 7 章
Bastien Guerry’s column view tutorial

日期和时间

为了支持工程的计划,TODO 项可以标记上日期和/或时间。带有日期和时间信息的特定格式的字符串在 Org 模式中称为时间戳。

时间戳

时间戳是一个具有特定格式的日期(可能带有时间和时间段)说明,例如 <2005-10-01 Tue><2003-09-16 Tue 09:39> ,或者 <2003-09-16 Tue 12:00-12:30> 。 时间戳可以出现在树条目的标题和正文的任何地方。它能使条目只在特定的日期才出现在议程列表中。

普通时间戳;事件;约会

一个简单的时间戳只是给一个条目加上时间和日期。这跟在纸质的议程上写下约会和事件是一样的。

* Meet Peter at the movies <2006-11-01 Wed 19:15>
* Discussion on climate change <2006-11-02 Thu 20:00-22:00>

具有时间间隔的时间戳

一个时间戳可以包含一个时间间隔,表示事件不只在指定的时间发生,还在每隔一个特定的时间如 N 天(d)、周(w)、月(m)或者年(y)之后重复发生。下面的事件每周二在议程中显示:

* Pick up Sam at school <2007-05-16 Wed 12:30 +1w>

日记样式的 sexp 条目

为了能定义更复杂的时间,Org 模式支持 Emacs 日历/日记包(calendar/diary package)中的日记条目。例如:

* The nerd meeting on every 2nd Thursday of the month
,  <%%(diary-float t 4 2)>

时间/日期段

两个时间戳用‘–’连接起来就定义了一个时间段:

** Meeting in Amsterdam
,   <2004-08-23 Mon>--<2004-08-26 Thu>

非激活的时间戳

跟普通时间戳一样,但是这里是方括号而不是尖括号。这种时间戳是未激活的,它 会让一个条目显示在议程中。

* Gillian comes late for the fifth time [2006-11-01 Wed]

创建时间戳

时间戳要有特定的格式,这样才能被 Org 模式识别。下面的命令可以用来正确地处理时间戳的格式。

C-c .询问日期并输入正确的时间戳。当光标处理一个时间戳之上时,是修改这个时间戳,而不是插入一个新的。如果这个命令连用再次,就会插入一个时间段。加上前缀会附带当前时间。
C-c !功能同 C-c .,但是插入的是一个未激活的时间戳。
S-LEFT/RIGHT将光标处理的时间戳改变一天。
S-UP/DOWN改变时间戳中光标下的项。光标可以处在年、月、日、时或者分之上。当时间戳包含一个时间段时,如 “15:30-16:30”,修改第一个时间,会自动同时修改第二个时间,以保持时间段长度不变。想修改时间段长度,可以修改第二个时间。

当 Org 模式询问时间/日期时,能接收任何包含时间和/或日期的字符串,它能根据当前的时间日期智能地分析字符串,从而得到没有指明的信息。你也可以用弹出的日历中选择日期。想完整地了解时间/日期询问的工作方式,可以参考手册。

截止期限和计划安排

时间戳前面可以加一些关键字来协助计划安排。

截止期限

意义:任务(大多数情况都会是一个 TODO 项,当然也可以不是)应该完成的日期。

C-c C-d在标题下面一行插入一个带有“DEADLINE”关键字的时间戳。

截止日期任务 会列在 议程 中。另外, 今天的议程 会在任务到期 orgdeadline-warning-days 天前对即将即将到期以及已经过期的任务给出提醒,直到任务被标记为 DONE。例如:

*** TODO write article about the Earth for the Guide
,    The editor in charge is [[bbdb:Ford Prefect]]
,    DEADLINE: <2004-02-29 Sun>

日程安排

意义:你计划在给定的那个日期开始进行那项任务。[fn:9]

在给定的日期标题会列在议程中。[fn:10]另外,对于过期的日程安排会在编辑为 今天 并给出提醒,直到被标记为 DONE。也就是说,任务会自动推迟日期直到它被完成。

C-c C-s在标题下面插入一个带有“SCHEDULED”关键字的时间戳。
*** TODO Call Trillian for a date on New Years Eve.
,    SCHEDULED: <2004-12-25 Sat>

有些任务需要一再重复出现。Org 模式在截止期限、计划安排和普通时间戳中用所谓的中继器来管理这种任务。在下面的例子中:

** TODO Pay the rent
,   DEADLINE: <2005-10-01 Sat +1m>

+1m 是一个中继器;上面的意思是任务有一个截止期限 <2005-10-01> ,并从这个日期开始每月都重复出现。

记录工作时间

使用 Org 可以记录在一个工程中花在某些特定任务上的时间。

l 键可能会在时间轴(见第 10.3.4 节)和议程(见第 10.3.1 节)中使用来查看一天中处理和关闭了哪些任务。

C-c C-x C-i开始当前条目的计时(clock-in)。这会插入一个 CLOCK 关键字和一个时间戳。加上 C-u 前缀,从当前已经计时的任务中选择任务。
C-c C-x C-o停止计时(clock-out)。这会在开始计时的地方插入另一个时间戳。它会直接计算使用时间并插入到时间段的后面如 “=> HH:MM”。
C-c C-x C-e为当前的计时任务更新进度。
C-c C-x C-x取消当前的计时。当你误操作打开一个计时时,或者转而去做其他事情时,这个命令就很有用。
C-c C-x C-j跳转到包含当前正在运行的计时的任务条目。用 C-uf 前缀从当前计时的任务中选择。
C-c C-x C-r在当前文件插入一个包含像 Org 表格一样的计时报告的动态块。当光标正处于一个存在的块上时,更新它。
#+BEGIN: clocktable :maxlevel 2 :emphasize nil :scope file
#+END: clocktable
如何定制视图,见手册。
C-c C-c在一个已经存在的计时表格之上时,更新它。 更新动态块。光标需要置于动态块 #+BEGIN 这行。

扩展阅读
手册第 8 章\ Charles Cave’s Date and Time tutorial\ Bernt Hansen’s clocking workflow

区块

Org-mode 使用 begin…end 块来实现很多功能,比如引入源代码.在这些区块的第一行上按 TAB 键可以折叠/扩展该区块.

折叠区块

你也可以在设置在启动时自动折叠所有的块,方法是配置变量’org-hide-block-startup’或者在每个文件加上

代码

C-c C-, 可以快速插入不同类型的代码块

代码块的结构

#+NAME: <name>
   <body>

其中

  • #+NAME 行是可选的,并常用来为代码块命名,以方便在其他地方(可以跨文件)调用该代码块. <name> 应该是唯一的,否则结果未定义
  • <language> 指明了代码块中的代码是哪种语言的代码
  • <switchers> 也是可选的,它控制了代码块的导出方式
  • <header arguments> 也是可选的,它控制了代码块的执行,导出与抽取的各方面的行为. <header arguments> 还可以通过 buffer 或 subtree 的属性来控制
  • <body> 为代码块的具体内容

编辑代码块

使用 C-c ' 来编辑当前的代码块. 它会新开一个编辑 buffer,进入<language>的 major mode,并插入代码块的原内容. 在该编辑 buffer 中按 C-x C-s 会将编辑 buffer 中的内容写回原代码块. 若编辑完后,想退出编辑窗口,再按一次 C-c ' 即可.

设置自动保存

你可以通过设置 org-edit-src-auto-save-idle-delay 的值来设置空闲多少秒后自动保存 buffer 内容. 或者通过设置 org-edit-src-turn-on-auto-save 来让进入代码块后自动开启 auto-save-mode

设置进入 buffer 后的行为

在按 C-c ' 进入编辑 buffer 后,会自动激活 org-src-mode. 同时,还可以通过以下变量来设置编辑 buffer 的其他行为(更多配置项请参见配置组 org-edit-structure)

  • org-src-lang-modes

    <lang>-mode 存在,则默认编辑 buffer 会进入该 major-mode. 但通过设置该变量可以映射任意的 <lang> 为其他的 major-mode

  • org-src-window-setup

    该变量控制了当创建编辑 buffer 后,各 window 怎么排列

  • org-src-preserve-indentation

    该变量控制了是否保持代码块中的空格为空格,而不转换为 TAB.

    默认为 nil,表示将代码块中的空格转换为 TAB. 当代码块中的代码为类似 python 这种对空格缩进很严格的语言时,最好设置为 t

  • org-src-ask-before-returnning-to-edit-buffer

    当已经存在编辑 buffer 的情况下,再次按下 C-c ',该变量控制是否弹出提示.

  • org-src-fontify-natively

    org buffer 中,也高亮显示代码块中的代码.

导出代码块及其结果

:exports 这一 header argument 控制了导出 org 文件时是否导出代码块及其执行结果

  • :exports code

    大多数语言的默认设置(ditta 是个例外). 表示只导出代码块的内容

  • :exports results

    表示导出结果

  • :exports both

    代码块及其计算结果都被导出

  • :exports none

    代码块及其计算结果都不会被导出

org-export-babel-evaluate 变量可以控制在导出 org 时,哪些代码块可以被执行

nil
所有代码块都不会执行,这在包含有不安全的代码块时特别有用
inline-only
只有 inline 代码块会被执行. 非 inline 代码块需要人手工执行,这一特性常用于避免在导出时执行过于消耗资源的代码

执行代码块

执行的结果与代码块之间会有一行间隔文本,该间隔默认为 #+RESULTS (该值由 org-babel-results-keyword 的值决定). 若代码块的 Header argument 开启了 cache,则间隔行文本还可能有一个 cache 标识符

默认只有 emacs-lisp 的代码块能够被执行,但是可以通过设置 org-babel-load-languages 的值来决定哪些语言的代码块能够被执行.

最简单的执行代码块的办法就是把光标定位到代码块中,然后按下 C-c C-c

若为代码块命名了,则可以在 org buffer 或 org table 的任意地方执行该代码块. 但前提是该代码块位于当前 org buffer 或 Library of Babel 中.

执行指定名称代码块的方法为使用单独的 #+CALL: 行或它的嵌入式语法

#+CALL: 的语法为:

#+CALL: <name>(<arguments>)
#+CALL: <name>[<inside header arguments>](<arguments>) <end header arguments>

其嵌入式语法为:

... call_<name>(<arguments>) ...
... call_<name>[<inside header arguments>](<arguments>)[<end header arguments>] ...

其中:

  • <name>

    要执行代码块的名字

  • <arguments>

    传递给代码块的参数,该参数会覆盖代码块 header argument 中的参数值. 下面是一个例子

    #+CALL: double(n=4)
        
  • <inside header arguments>

    这些参数会被应用到指定的代码块中去,从而影响代码块的执行. 例如 [:result output] 就会搜集代码块执行过程中所有输出到 STDOUT 中的结果

  • <end header arguments>

    这些参数作用于”calling instance”而并不会影响到指定代码块的执行. 这些参数影响的是执行结果如何插入到 org buffer 中以及 call line 语句本身 export 时的参数.

    例如: [:results html] 会在插入执行结果时,用 BEGIN_HTML: 块包裹起来.

Library of Babel

存放在 Library of Babel 中的代码块可以被任意 org 文件调用.

The central repository of code blocks in the “Library of Babel” is housed in an Org mode file located in the ‘contrib’ directory of Org mode.

要想将某个代码块加入到 Library of Babel 中,只需要调用函数 org-babel-lob-ingest 即可,该函数的快捷键为 C-c C-v i

header arguments

设置 header arguments

一般来说 header arguments 作用域越大的优先级越低

  • 设置全系统的 header arguments

    设置 org-babel-default-header-args 变量可以设置全系统的 header arguments. 它的默认值为

    ((:session . "none")
     (:results . "replace")
     (:exports . "code")
     (:cache . "no")
     (:noweb . "no")
     (:hlines . "no")
     (:tangle . "no"))
        
  • 为某种语言设置 header arguments

    通过设置变量 org-babel-default-header-args:<lang> 的变量值可以为特定语言设置默认 header arguments. 这里<lang>替换为代码块的语言名称

  • 为 heading 设置 header arguments

    通过设置 heading 名为 header-argsheader-args:<lang> 属性,可以为某个 heading 下的所有代码块设置 header arguments.

    这种情况下,无论 org-use-property-inheritance 的值是什么, 这些属性一定是基础的.

    #+PROPERTY: header-args:R  :session *R*
    #+PROPERTY: header-args    :results silent
        

    * outline header
    :PROPERTIES: 
    :header-args: :cache yes
    :END:      
        
  • 为某代码块设置 header arguments

    为独立的代码块设置自己的 header arguments 是最普遍也是最灵活的方式. 方法是在 #+BEGIN_SRC 行后列上一系列的 header arguments 及其值即可. 例如

    #+NAME: factorial
    #+BEGIN_SRC haskell :results silent :exports code :var n=0
       fac 0 = 1
       fac n = n * fac (n-1)
    #+END_SRC
        

    当然也可以为嵌入式代码块设置 header arguments. 例如

    src_haskell[:exports both]{fac 5}
        

    代码块的 header aguments 还可以分拆到多个 #+HEADER:#+HEADERS: 行中,这些行放在 #+BEGIN_SRC 之前 #+NAME: 之后. 例如

    #+HEADERS: :var data1=1
    #+BEGIN_SRC emacs-lisp :var data2=2
          (message "data1:%S, data2:%S" data1 data2)
    #+END_SRC
    
    #+RESULTS:
    : data1:1, data2:2
        

    #+NAME: named-block
    #+HEADER: :var data=2
    #+BEGIN_SRC emacs-lisp
      (message "data:%S" data)
    #+END_SRC
    
    #+RESULTS: named-block
    : data:2
    
        
  • 设置调用代码块时的 header arguments

    请参见 `执行代码块’ 这一节

header arguments 说明

var

:var 参数用于传递参数給代码块. 传递参数給代码块的具体方式,依各个语言的不同而改变,具体需要阅读特定语言的文档.

当为代码块设置 :var 参数时,总是需要为它设置一个默认值

参数的值可以是字面量,引用甚至是 Emacs Lisp 代码. 其中引用可以是带有 #+NAME:, #+RESULTS: 说明的 table 或 list. #+BEGIN_EXAMPLE 块,其他代码块以及其他代码块的运行结果. 需要注意的是,让引用另外的代码块时,被引用的代码块会被执行,除非被引用的代码块已经被缓存了运行结果

:var 的格式为 :var name=assign 其中 assign 可以是

  • table 的引用
    #+NAME: example-table
    | 1 |
    | 2 |
    | 3 |
    | 4 |
    
    #+NAME: table-length
    #+BEGIN_SRC emacs-lisp :var table=example-table
      (length table)
    #+END_SRC
    
    #+RESULTS: table-length
    : 4
        
    • list 的引用
      #+NAME: example-list
      - simple
        - not
        - nested
      - list
                    
      #+BEGIN_SRC emacs-lisp :var x=example-list
        (print x)
      #+END_SRC
        
      #+RESULTS:
      | simple | list |
              
    • 不带参数的代码块
      #+BEGIN_SRC emacs-lisp :var length=table-length()
        (* 2 length)
      #+END_SRC
      
      #+RESULTS:
      : 8
              
    • 带参数的代码块
      #+NAME: double
      #+BEGIN_SRC emacs-lisp :var input=8
        (* 2 input)
      #+END_SRC
      
      #+RESULTS: double
      : 16
      
      #+NAME: squared
      #+BEGIN_SRC emacs-lisp :var input=double(input=1)
        (* input input)
      #+END_SRC
      
      #+RESULTS: squared
      : 4
              
    • example 块
      #+NAME: literal-example
      #+BEGIN_EXAMPLE
        A literal example
        on two lines
      #+END_EXAMPLE
      
      #+NAME: read-literal-example
      #+BEGIN_SRC emacs-lisp :var x=literal-example
        (concatenate 'string x " for you.")
      #+END_SRC
      
      #+RESULTS: read-literal-example
      : A literal example
      :   on two lines for you.
      
              
    • 可索引的变量值

      可以通过索引来切取变量的部分值. 索引从 0 开始,且支持负数,表示从后往前算.

      org 支持嵌套索引,其意义类似于多重数组的索引,方法是在索引与索引之间用`,’分隔

      #+NAME: example-table
      | 1 | a |
      | 2 | b |
      | 3 | c |
      | 4 | d |
      
      #+BEGIN_SRC emacs-lisp :var data=example-table[0,-1]
        data
      #+END_SRC
      
      #+RESULTS:
      : a
      
      
      #+NAME: 3D
      #+BEGIN_SRC emacs-lisp
        '(((1  2  3)  (4  5  6)  (7  8  9))
         ((10 11 12) (13 14 15) (16 17 18))
         ((19 20 21) (22 23 24) (25 26 27)))
      #+END_SRC
      
      #+BEGIN_SRC emacs-lisp :var data=3D[1,,1]
        data
      #+END_SRC
      
      #+RESULTS:
      | 11 | 14 | 17 |
      
              

      org 还支持切片操作,方法是在两个索引之间使用`:’分隔

      #+NAME: example-table
      | 1 | a |
      | 2 | b |
      | 3 | c |
      | 4 | d |
      | 5 | 3 |
      
      #+BEGIN_SRC emacs-lisp :var data=example-table[1:3]
        data
      #+END_SRC
      
      #+RESULTS:
      | 2 | b |
      | 3 | c |
      | 4 | d |
              

      Additionally, an empty index, or the single character ‘*’, are both interpreted to mean the entire range and as such are equivalent to ‘0:-1’

      #+NAME: example-table
       | 1 | a |
       | 2 | b |
       | 3 | c |
       | 4 | d |
      
       #+BEGIN_SRC emacs-lisp :var data=example-table[,0]
         data
       #+END_SRC
      
       #+RESULTS:
       | 1 | 2 | 3 | 4 |
      
              
    • Emacs lisp 代码

      若变量的值是以 `(‘,`[‘,`”或“’ 开头的,则它被认为是 Emacs lisp 代码,其代码的运行返回值才会作为变量真正的值. 例如:

      #+BEGIN_SRC sh :var filename=(buffer-file-name) :exports both
         wc -w $filename
      #+END_SRC
              

      需要注意的是,若是从 table 或 list 中读取到的值是以 `(‘,`[‘,`”,“’开头的, 也不会被认为是 elisp 代码

      #+NAME: table
       | (a b c) |
      
       #+HEADERS: :var data=table[0,0]
       #+BEGIN_SRC perl
         $data
       #+END_SRC
      
       #+RESULTS:
       : (a b c)
              

results

有四种类型的 :result 参数. 对于某个代码块来说,每种类型的 :reslt 参数值只能有一个. 这四种类型分别为:

  • collection: specify how the results should be collected from the code block
    value
    默认值,表示 result 为代码块中最后一个语句的返回值,代码块的内容会被包含在一个函数中,然后执行该函数. 因此对于像 Python 这样的语言来说,若最后语句不是 return,则一定返回 None
    output
    result 为代码块输出到 STDOUT 中的结果,返回的是解释器的输出结果.
  • type: specify what type of result the code block will return—which has implications for how they will be processed before insertion into the Org mode buffer

    默认情况下,result 会以 table 或 scalar 的形式插入到 org buffer 中

    table/vector
    result 一定以 table 的形式插入到 org buffer 中. 即使 result 的值是一个单值,也会被转换为一个单行单列的表格.
    list
    result 会以 org list 的形式插入到 org buffer 中. 即使 result 的值是一个单值,也会转换为一个只有一个元素的 list
    scalar/verbatim
    直接插入 result 的字面量,不做任何转换
    file
    result 的值被认为是一个指向 file 的路径. result 的值会被转换为一个 file link 再插入到 org buffer 中
  • format: specify what type of result the code block will return—which has implications for how they will be inserted into the Org mode buffer
    raw
    result 的值被看成是 raw org mode code,会被不做任何转换地插入 org buffer 中. 若 result 的值看起来是一个 org table,则还会被自动排列整齐.
    org
    result 的值会被包裹进 BEGIN_SRC org 代码块中(但默认情况下,result 的值不会被逗号转义)
    html
    result 的值被认为是一段 html 代码,因此会被包裹进 BEGIN_HTML 块中
    latex
    result 的值被认为是一段 latex 代码,因此会被包裹进 BEGIN_LaTex 块中
    code
    result 的值被认为是一段可解析的代码,因此会被包裹进代码块中.
    pp
    result 的值被认为是一段可解析的代码,但在包裹进代码块之前会进行格式美化操作(converted to pretty-printed code). 目前只支持 Python 与 Ruby
    drawer
    result 的值会被包裹进一个 RESULTS drawer 中
  • handing: specify how the results of evaluating the code block should be handled.
    silent
    result 会显示在 minbuffer 中,而不会插入到 org buffer 中
    replace
    默认值. 之前插入的的 result 会被删除,然后插入新的 result 结果
    append
    新的 result 会插入到之前 result 的后面
    prepend
    新的 result 会插入到之前 result 的前面.

file

:file 参数用于指定将代码块的 result 保存到哪个文件中. 常与 :results file 配合使用

代码块执行后,会插入一条 \[[file:]\] 的链接到 org buffer 中.

:file 的参数值可以有两种格式:

  • 一个表示文件路径的字符串
  • 一个由连个字符串组成的 list. 其中第一个字符串为保存的文件路径,第二个字符串为链接的描述

file-desc

:file-desc 参数常与 :file 参数配合使用,用于提供链接的描述

dir

:dir 参数指定了代码块执行的工作目录. 同时它也常常与 :file 参数联用用于指明输出文件的相对路径. 默认情况下为 org buffer 的当前目录. 例如:

#+BEGIN_SRC R :file myplot.png :dir ~/Work
   matplot(matrix(rnorm(100), 10), type="l")
#+END_SRC

:dir 甚至还支持 tramp 格式的远程路径,这表示代码块是在远程机器上执行的. 例如

#+BEGIN_SRC R :file plot.png :dir /[email protected]:
plot(1:10, main=system("hostname", intern=TRUE))
#+END_SRC

上面这段代码,会在 org buffer 中插入这么一条链接

[[file:/scp:[email protected]:/home/dand/plot.png][plot.png]]

:dir 参数的实现原理实际上就是更改 default-directory 的值

exports

:exports 参数指定了当将 org file 导出为 HTML 或 LaTex 时,是否包含代码块或其 result

code
默认值,包含代码块的内容
results
包含代码块的 results
both
包含代码块及其 results
none
都不包括

tangle

:tangle tangle 是一个 bool 值的参数,取值为 yes,no,filename ,其作用是将所有源代码导出到一个文件。

no
默认值,表示不抽取出该代码块中的代码
yes
抽取出代码块中的代码,存放的文件命为将该 org 文件后的 .org 替换为代码块语言后缀后的名称
filename
抽取出代码块中的代码,存放在 filename 中

mkdirp

:mkdirp 用于决定当 tangled file 中的目录不存在时,是否创建该目录

yes
主动创建不存在的目录
no
不自动创建不存在的目录

comments

默认情况下 tangle 的过程只会把源代码的内容插入到外部文件中. 使用 :comments 参数可以让代码在 tangle 的过程中插入额外的注释信息

no
默认情况,表示不插入额外的注释
link
插入额外的注释,一遍从源代码中能够链接回原 org 文件
yes
link 一样,只是为了向后兼容
org
将一部分 org 文件中的内容作为注释插入源文件中.The text is picked from the leading context of the tangled code and is limited by the nearest headline or source block as the case may be
both
link + org
noweb
开启 link,同时 wraps expanded noweb references in the code block body in link comments.

padline

:padline 参数决定了 tangle 时,是否在各个代码块之间使用空行间隔

yes
在各代码块之间使用空行间隔
no
代码块之间不使用空行间隔

no-expand

默认情况下,代码块中的代码需要先经过 org-babel-expand-src-block 的扩展后再 tangle 到源文件中. 这一过程涉及到替换 :var 中定义的参数与 noweb 引用

:no-expand 则会禁止这项操作

session

:session 会让运行代码块的进程保持不关闭. 该功能只能对解析型的语言有效.

默认情况下,进程运行代码块后会自动退出

传递給 :session 的字符串会作为 session 的名称.

noweb

:noweb 参数控制了在执行,tangle 和 export 代码块时,如何展开 noweb 引用

no
默认值,并不展开 noweb 引用
yes
在 evaluated,tangled 和 exported 前,展开 noweb 引用
tangle
只有 tangle 前,才展开 noweb 引用
no-export
tangle 或 evalute 前才展开 noweb 引用
strip-export
evalute 或 tangle 前才会展开 noweb 引用,且 export 前会把 noweb 引用删除
eval
只有在 evaluate 前才展开 noweb 引用

noweb-ref

当扩展”noweb”引用时, 会扩展为任何名字或 :noweb-ref 参数为引用名字的代码块的内容的和. 例如

#+BEGIN_SRC sh :tangle yes :noweb yes :shebang #!/bin/sh
  <<fullest-disk>>
#+END_SRC

#+RESULTS:
: 83% /cygdrive/d

* the mount point of the fullest disk
  :PROPERTIES:
  :noweb-ref: fullest-disk
  :END:

** query all mounted disks
#+BEGIN_SRC sh
  df \
#+END_SRC

** strip the header row
#+BEGIN_SRC sh
  |sed '1d' \
#+END_SRC

** sort by the percent full
#+BEGIN_SRC sh
  |awk '{print $5 " " $6}'|sort -n |tail -1 \
#+END_SRC

** extract the mount point
#+BEGIN_SRC sh
  |awk '{print $2}'

当 tangle 最上面那个代码块时,实际的内容整合了”the mount point of the fullest disk” headline 下的所有代码块的内容

noweb-sep

:noweb-sep 参数设置了整合各个代码块内容时,各代码块之间使用哪个字符串来分隔,默认为一个空行

cache

:cache 参数决定了是否缓存代码块的执行结果. 但当对带有:session 参数的代码块无效

no
默认,不对代码块的执行结果进行缓存
yes
对代码块的结果进行缓存.org 会将代码块的内容做一个 SHA1 哈希计算,并在计算前做一次比较,若代码块并未改变则直接使用该缓存值.

下面是一个例子:

#+NAME: random
#+BEGIN_SRC R :cache yes
runif(1)
#+END_SRC

#+RESULTS[a2a72cd647ad44515fab62e144796432793d68e1]: random
0.4659510825295

#+NAME: caller
#+BEGIN_SRC emacs-lisp :var x=random :cache yes
x
#+END_SRC

#+RESULTS[bec9c8724e397d5df3b696502df3ed7892fc4f5f]: caller
0.254227238707244

sep

The ‘:sep’ header argument can be used to control the delimiter used when writing tabular results out to files external to Org mode. This is used either when opening tabular results of a code block by calling the ‘org-open-at-point’ function bound to ‘C-c C-o’ on the code block, or when writing code block results to an external file (see *note file::) header argument.

By default, when ‘:sep’ is not specified output tables are tab delimited.

hlines

:hline 参数决定了当使用一个 table 作为输入时,是否去掉 table 中的 hline. 默认为 no,因为 table 总的 hline 会被转换为 hline symbol. 而这常常是一种干扰.

no
去除 input table 中的横线
yes
保留 input table 总的横线

下面是一个例子

#+NAME: many-cols
| a | b | c |
|---+---+---|
| d | e | f |
|---+---+---|
| g | h | i |

#+NAME: echo-table-1
#+BEGIN_SRC python :var tab=many-cols
  return tab
#+END_SRC

#+RESULTS: echo-table-1
| a | b | c |
| d | e | f |
| g | h | i |


#+NAME: echo-table-2
#+BEGIN_SRC python :var tab=many-cols :hlines yes
  return tab
#+END_SRC

#+RESULTS: echo-table-2
| a | b | c |
|---+---+---|
| d | e | f |
|---+---+---|
| g | h | i |

colnames

:colnames 参数决定了当使用一个 table 作为输入时,是否将第一行的值看成是列名而去除.

nil
默认值. 当第二行是一个 hline 时,则认为第一行为列名去除掉.
no
第一行不是列名,不要去除
yes
第一行作为列名去掉,然后 再按照 nil 来处理
#+NAME: less-cols
| a |
|---|
| b |
| c |

#+NAME: echo-table-again
#+BEGIN_SRC python :var tab=less-cols
  return [[val + '*' for val in row] for row in tab]
#+END_SRC

#+RESULTS: echo-table-again
| b* |
| c* |

请注意, 去除列名的动作发生在使用 index 切片之前

rownames

:rownames 参数决定了当使用一个 table 作为输入时,是否将第一列的值看成是行名而去除. 默认为 no

no
第一列不是行名
yes
第一列是行名
#+NAME: with-rownames
| one | 1 | 2 | 3 | 4 |  5 |
| two | 6 | 7 | 8 | 9 | 10 |

#+NAME: echo-table-once-again
#+BEGIN_SRC python :var tab=with-rownames :rownames yes
  return [[val + 10 for val in row] for row in tab]
#+END_SRC

#+RESULTS: echo-table-once-again
| one | 11 | 12 | 13 | 14 | 15 |
| two | 16 | 17 | 18 | 19 | 20 |

请注意, 去除行名的动作发生在使用 index 切片之前

shebang

:shebang 参数设置 shebang 行,它在 tangling 时会将值插入到 tangled file 中的第一行去,并将其标识为可执行的.

tangle-mode

:tangle-mode 参数设置 tangled file 的权限模式. 它的值会被传递给函数 set-file-modes. 它的值会覆盖 :shebang 的效果

当多个代码块 tangling 到同一个 file,而各代码块的 :tangle-mode 不相同的话,其结果是未知的.

eval

:eval 参数决定了什么情况下可以执行代码块中的代码. 默认情况下的行为由变量 org-confirm-babel-evaluate 的值决定

never/no
任何条件下都不能执行
query
询问是否执行
never-export/no-export
在 export 时不能执行,但可以手工执行
query-export
export 时询问是否执行

wrap

:wrap 用于决定将代码块的执行结果用什么标识符包裹起来.

任意传递給 :wrap 的<string>,都会将结果包裹在 #+BEGIN_<string>#+END_<string>

若只有一个单独的 :wrap,则结果会包裹在 #+BEGIN#+END_RESULTS

post

:post 参数用于决定了得到代码块的 result 后,该 result 要传递到哪个代码块中作进一步的处理. 这时,result 的值临时绑定到 *this* 变量中. 例如

#+name: attr_wrap
#+begin_src sh :var data="" :var width="\\textwidth" :results output
  echo "#+ATTR_LATEX :width $width"
  echo "$data"
#+end_src

#+header: :file /tmp/it.png
#+begin_src dot :post attr_wrap(width="5cm", data=*this*) :results drawer
  digraph{
          a -> b;
          b -> c;
          c -> a;
  }
#+end_src

#+RESULTS:
:RESULTS:
#+ATTR_LATEX :width 5cm
[[file:/tmp/it.png]]
:END:

prologue

:prologue 参数决定了在执行代码块中的代码之前,作什么初始化操作

epilogue

:epilogue 参数决定了在执行代码块中的代码之后,作什么清理操作

处理代码块的运行结果

:session:resultsvalue 还是 output 共同决定了 results 的结果

Non-sessionsession
:results value最后语句的返回值最后语句的返回值
:results outputSTDOUT 的输出解释器的输出结果

当 =:results value= 时,无论是否开启 =:session= ,results 都会尽可能的以 table 的方式展示出来

当 =:results value= 时,代码块的内容会被包含在一个函数中,然后执行该函数. 因此对于像 Python 这样的语言来说,若最后语句不是 return,则一定返回 None

注意 =:results output= 在 session 与 non-session 时的不同

#+BEGIN_SRC python :results output
 print "hello"
 2
 print "bye"
#+END_SRC

#+RESULTS:
: hello
: bye


#+BEGIN_SRqC python :results output :session
 print "hello"
 2
 print "bye"
#+END_SRC

#+RESULTS:
: hello
: 2
: bye

代码块相关快捷键与函数

在代码块中

‘C-c C-c’‘org-babel-execute-src-block’
‘C-c C-o’‘org-babel-open-src-block-result’
‘M-<up>’‘org-babel-load-in-session’
‘M-<down>’‘org-babel-switch-to-session’

引用

在 Org Mode 中引用文字非常简单,按如下方式写即可:

引用的文字

Capture(捕获) - Refile(整理) - Archive(归档)

Capture

设置 capture 的记录保存位置和快捷键

(setq org-default-notes-file (concat org-directory "/notes.org"))
(define-key global-map "\C-cc" 'org-capture)

快速输入 #+BEGIN_SRC … #+END_SRC

用 org-mode 写文章的的时候,经常需要引用代码片段或者程序输出,这就需要输入 #+BEGIN_SRC … #+END_SRC 或者 #+BEGIN_EXAMPLE … #+END_EXAMPLE 。输入的次数多了,就会想办法自动化,要么是用宏,要么是手工写 elisp 函数,要么是借助 yasnippets 或者 skeleton 框架来写代码片段(比如 Emacs 中文网 就发过一篇 《GNU Emacs Org-mode 写作的几个快捷方式》 ,那是借助 skeleton 来实现的)。

但其实,org-mode 已经内置了快速输入的方法: 输入 <s 再按 TAB 键 ,就会自动展开为 #+BEGIN_SRC … #+END_SRC 。类似地,输入 <e 再按 TAB 键,就会自动展开为 #+BEGIN_EXAMPLE … #+END_EXAMPLE 。

导出

C-c C-e 导出命令

生成目录表

如果想在导出成 HTML 时在文档前面生成一个章节目录表(Table of Contents),那么可以在文件头部的 OPTIONS 里面添加 toc:t 参数

#+OPTIONS: toc:t  ^:nil author:nil num:2

也可以设置 org-export-with-toc 这个变量

(setq org-export-with-toc t)

如果只想针对前面两个级别生成目录表,可以设置该值为相应的数字

#+OPTIONS: toc:2  ^:nil author:nil num:2

为每个分节的标题添加标号

导出成 HTML 时,如果不自定义 css(这个高级话题留待下次再说),那么 h1, h2, h3 各个级别的标题只会字体大小有 点不同,不会呈现不同颜色,不会有缩进,于是阅读起来各节之间的关系就搞不清楚了。可以设置 org-export-with-section-numbers 让导出时为各章节的标题添加 1.2.3 这样的

比如:

* header foobar

** header hello

** header welcome

* header hehe
some text here

** header haha

*** low level

导出时会变成:

1 header foobar

1.1 header hello

1.2 header welcome

2 header hehe
some text here

2.1 header haha

2.1.1 low level

如果只想针对前面两个级别生成分节号,可以设置该值为相应的数字。比如上面的例子如果设置 org-export-with-section-numbers 为 2 ,导出时就变成了:

1 header foobar

1.1 header hello

1.2 header welcome

2 header hehe
some text here

2.1 header haha

*low level*

禁用下划线转义

org-mode 的文档在导出到 html 时,有一个问题就是 abc_def 会变成类似于 latex 的下标形式.类似的 10^24 会变成上标形式.

关闭这个功能的方法是在 org 文件头部的 OPTIONS 里面添加 ^:nil:

#+OPTIONS: ^:nil

上面的方法是针对当前文件的,如果想针对所有文件缺省关闭这个功能,需要在 ~/.emacs 中设置:

(setq-default org-use-sub-superscripts nil)

让不同级别的标题采用不同大小的字体

定制一下 org-level-1, org-level-2 等 face 的 height 属性就可以了(不过如果你用了其它 theme 的话, 要在加载这些 theme 之后再执行一遍下面这些配置,或者你把它们放在 org-mode-hook 中去执行):

(set-face-attribute 'org-level-1 nil :height 1.6 :bold t)
(set-face-attribute 'org-level-2 nil :height 1.4 :bold t)
(set-face-attribute 'org-level-3 nil :height 1.2 :bold t)))

导出/2020-06-03_20-31-21_tangotango_org.png

两个与中文相关的问题

不关闭中文输入法,输入章节标题里面的星号

频繁打开/关闭输入法还是挺翻的,比如在连续输入章节或者列表项时,输入章节前面的 * 或者 列表项 前面的 * 或者 - 号,都要先关闭输入法,否则输入的是 × 和

不过可以用下面的方法解决:

(defun org-mode-my-init () ; ...... (define-key org-mode-map (kbd “×”) (kbd “*”)) (define-key org-mode-map (kbd “-”) (kbd “-“)) )

(add-hook ‘org-mode-hook ‘org-mode-my-init)

中英文字体混排时的表格对齐问题

org-mode 的表格功能还是比较酷的,用起来相当方便(比较大的缺点是不支持跨列或者跨行合并单元格,甚至简单 一点,表格的某一行实际两行来存放内容(就是类似 html 编辑器里面那种单元格自动折行的显示方式)也不行)。

对于中文用户来说,最容易碰到的一个问题是一旦表格中同时有中英文的话,表格会无法对齐,中文比较少的时候 还好,只会有一点点错位,但当中文比较多时,这个表格就乱成一团,没法看了。

orgtable-unaligned

(本图非本人制作,摘自: 让中英混杂的 orgmode table 对齐)

这个问题困扰了很多人,大家也 折腾了各种方法。

首先是有人留意到,其实不仅仅是 org-mode 里面有问题,emacs 本身在中英文混排时一个中文字符就跟两个英文字符 不是同样宽度的,除非有时碰巧了(比如当初我在 Ubuntu 下用 Ubuntu Mono 作为 emacs 默认字体时)。所以最开始我 一直在尝试各种字体,看哪种可以解决这个问题——但一直没有满意的方案,在一个机器上试验出来的结果在另外一 个系统上却不好使。最后发现是搞错了方向。

对于大部分的编辑器而言,我们只能选择一种字体(比如写代码常用的 DejaVu Sans Mono, Inconsolata, Consolas),但这个字体中可能仅包含英文字符(或者也包含了其它拉丁字符),但大部分情况下不包含 CJK 字符, 对这种情况下对 CJK 字符的显示都是由系统来处理的,编辑器自己一般都不管。

不过 Emacs 毕竟是神的编辑器啊,它可以做到对不同体系的字符指定具体的字体,所以解决这个问题的办法是: 针 对中英文指定不同大小的字体,英文用小字,中文用大字 (别问我为什么,我是没去仔细研究。下面有一堆链接, 有兴趣的自己去看吧)。

(set-default-font “DejaVu Sans Mono 10”) (set-fontset-font “fontset-default” ‘unicode”WenQuanYi Bitmap Song 12”) ;;for linux (set-fontset-font “fontset-default” ‘unicode “宋体 12”) ;; for windows 在你的环境上,你可能得对针对自己喜欢的编程字体去试验一下,看配哪个字号的中文字体(以及字号大小)可以 解决这个问题(或者可以试试下面的 font.pl)。如果你还有日文、韩文什么的,可以详细地针对各种 charset 设定 字体(而不是像上面笼统地用 ‘unicode 来制定),详情请参看 折腾 Emacs: 中文字体配置 | Emacs 中文网。

参考文章

关闭自动缩进

(electric-indent-mode -1)

Indentation in Org Mode Source Block with Return

参考文章

Org-mode 简明手册 强大的 Org mode(3): 表格的基本操作及公式、绘图 Org-mode的电子表格的简明教程