Skip to content

Latest commit

 

History

History
4229 lines (3343 loc) · 293 KB

GitHub-org-mode完整手册.org

File metadata and controls

4229 lines (3343 loc) · 293 KB

Org-Manual 7.8

总介

摘要 : org大概能够做什么的摘要

Org是一种通过纯文本方式来快速而有效地记录笔记,处理待办列表,做项目计划的mode.

Org通过一些NOTE文件来组织任务,这些NOTE文件用纯文本的方式包含了一些列的项目信息. Org是建立在Outline mode的基础之上的,Outline mode能够很好地组织大型文件的内容. 你可以使用可视的循环和结构编辑功能来帮助你编辑大纲树结构. 通过使用内置的表格编辑器,你也可以很容易地创建出一个表格. Org可以管理代办列表,设置最后期限,加时间戳,制定规划. 它动态的把这些东西显示在一个agenda中,在这个agenda中很好地集成了Emacs calendar和diary功能. 你可以用纯文本的方式记录各种类URL的连接,这些连接可以链接到网站,email,Usenet消息,BBDB(The insidious Big Brother Database)条目,和任何与项目有关的文件. 如果你想打印和分享这些记录,你可以把org导出为结构化的ASCII文件,比如HTML,或者iCalendar文件(仅限于TODO和日程条目). 它也可以作为发布工具,为一堆的相互链接的网页提供发布服务.

作为一个项目计划的环境,Org通过为大纲节点增加元数据的方式工作. 正是基于这些元数据,我们可以通过查询抽取特定的记录并且动态地创建agenda视图.

Org模式中也可以包含其他非org环境,这些环境运行你编辑文件中的内嵌源代码,更便利地执行代码,记录文档,进行文学化编程.

通过激活Orgtbl mode,任何major mode都能拥有Org的表格编辑功能,这些表格编辑功能不仅自动化,上下文敏感,而且具有电子表格(spreadsheet)的运算能力. 通过一个转换步骤,就可以用它来包含一个表格到任意文件类型中(比如LaTeX). 通过minor Orgstruct mode,可以在非Org mode中使用Org的结构编辑和列表创建功能.

Org保持简单的事情简单化. 当第一次使用它时,感觉它就是个简单易用的大纲编辑器. 它不强加给你复杂性,但是当你需要的时候,却会发现有大量的功能可以使用. Org就是一个工具盒,你可以为了不同的目的,通过的不同的途径来使用它,例如你可以把它看成是:

• 一个具有可见性的转换和结构编辑能力的outline mode扩展
• 一个记录结构化记录的ASCII系统和表格编辑器
• 一个TODO列表的编辑器
• 一个完整的日程表和计划规划工具,你可以设定工作的最后截止日期和规划执行日期.
• 一个GTD系统
• 一个简单的超文本系统,可以导出HTML和LaTeX格式的文件
• 一个发布工具,可以用来创建一套相互链接的网页
• 一个进行文学化编程的环境

有一个网站提供了最新版本的Org连接,还有附加信息,FAQ,和入门指导.这个网页就是http://orgmode.org

安装 : 下载org后,如何安装

注意:如果你使用的是Emacs或者XEmacs中自带的Org版本,请跳过这一步直接前往激活. 如果需要查看你Emacs中自带的Org是什么版本的,按下 M-x load-library RET org 然后再 M-x org-version.

如果你从网站上下载了Org,不管它是zip还是tar格式的分发包,也不管它是不是Git存档,你必须遵照下面的步骤来安装它: 解压Org分发包并进入解压的目录中,然后编辑顶层目录中的’Makefile’文件. 你必须设置Emacs的二进制执行文件的名字(一般是’emacs’或者’xemacs’),设置Lisp和Info文件存放的路径. 如果你没有权限访问全系统的目录,你只需要简单地把’lisp’子目录加入Emacs的load-path中,然后就可以运行org mode了.如果你用这种方法,需要把下面这一行加入’.emacs’文件中

(setq load-path (cons "~/path/to/orgdir/lisp" load-path))          

如果你想使用’contrib’子目录中的代码,你只需要加这么一句

(setq load-path (cons "~/path/to/orgdir/contrib/lisp" load-path))

现在用下面的shell命令来把lisp文件编译为字节格式

make

如果你只是从发布目录运行Org,这就是所有的步骤了. 如果你想要安装Org到系统目录中,指向下面命令(需要系统管理员权限)

make install

安装Info文件是系统依赖的,不同的系统使用的是不同的’install-info’程序. 下面的命令理论上应该可以正确的安装Info文件到大多数系统中,但如果没有正确的安装的话,欢迎发送BUG报告给我们[fn:1]

make install-info

然后把下面一行添加到’.eamcs’文件中. 这使得Emacs可以在需要的时候自动加载文件中的函数,而不用在Org mode已启动的时候就加载

(require 'org-install)

不要忘了激活Org,具体操作见下一节.

激活 : 如何为指定的buffer激活org模式 #<<Activition>>

为了保证后缀为’.org’的文件会使用Org mode,在’.emacs’文件中增加下面一行

(add-to-list 'auto-mode-alist '("\\.org\\'" . org-mode))

Org-mode缓冲区需要打开font-lock选项,默认情况下Emacs已经打开次选项[fn:2]. 有4个Org命令应该定义全局的快捷键(也就是说作用于在Emacs的任何地方,而不仅仅是Org缓存区),这四个org命令为’org-store-link’,’org-capture’,’org-agenda’和’org-iswitchb’. 下面是建议的绑定键设置,你可以按照自己喜欢的来修改键配置

(global-set-key "\C-cl" 'org-store-link)
(global-set-key "\C-cc" 'org-capture)
(global-set-key "\C-ca" 'org-agenda)
(global-set-key "\C-cb" 'org-iswitchb)

经过上面这些配置,所有后缀为’.org’的文件在打开时会直接进入Org-mode. 如果你想不这么配置,作为替代,把下面这句放到文件的一行也可以.

MY PROJECTS    -*- mode: org; -*-

这样,不管文件名是什么,在打开时都会进去Org-mode. 参见变量’org-insert-mode-line-in-empty-file’.

很多Org命令在选定文本块时会对文本块进行操作. 为了保证该特性被启用,你需要开启’transient-mark-mode’(在XEmacs总是’zmacs_regions’). 在Emacs23中默认是打开的,但是在Emacs22中,你需要自己打开,自己打开的命令为

(transient-mark-mode 1)

如果你不想使用transient-mark-mode,你可以通过鼠标选择一个区域,以这种方式来建立一个选定的文本块,或者在一定光标之前安两下’C-<SPC>’

反馈 : BUG报告,好的想法,补丁等等

如果你发现了Org有问题,或者你有疑问,建议和好的想法,请发邮件到Org的mailing list [email protected]. 如果你还不是这个mailing list的会员, 那么在版主批准之后,你的mail会被加入到mailing list中[fn:3].

如果你想报告BUG,请首先在最新版本的Org上复现这个BUG–如果你允许一个老旧版本的Org,很可能这个Bug已经被修复了. 如果依旧有问题,请写好报告并提供尽可能多的信息,包括Emacs的版本信息(用M-x emacs-version <RET>)和Org的版本信息(用M-x org-version <RET>),以及’.emacs’中Org的相关配置. 最简单的提交报告的方法就是执行命令’M-x org-submit-bug-report’. 这个命令会收集所有必要的信息并放到一个Emacs的mail缓存区中,这样你只需要添加你自己的描述就可以了. 如果你不会在Emacs中发送email,请拷贝这些内容并粘贴到自己常用的Email程序中.

有时候你面对的错误可能是由于Emacs或Org-mode配置错了. 在报告BUG之前,最后以最小客户化的形式启动Emacs然后复现这个BUG. 这样做常常能够帮助你确定这个问题是因为配置的关系还是Org-mode本身有问题. 你可以用下面这个命令来开启一个最低客户化的session

emacs -Q -l /path/to/minimal-org.el

如果你使用的是Emacs中自带的Org mode,那么上面哪个最小客户化的配置就没有必要了. 你可以直接用’emacs -Q’来打开Emacs. 一个典型的’minimal-org.el’配置文件可能包含如下内容

;;; Minimal setup to load latest `org-mode'

;; activate debugging
(setq debug-on-error t
      debug-on-signal nil
      debug-on-quit nil)

;; add latest org-mode to load path
(add-to-list 'load-path (expand-file-name "/path/to/org-mode/lisp"))
(add-to-list 'load-path (expand-file-name "/path/to/org-mode/contrib/lisp"))

;; activate org
(require 'org-install)

如果有错误发生,一个错误的跟踪栈对查找问题很有帮助(下面说明了如何创建一个跟踪栈). 通常提供一个简单的造成错误的简单例子会很有帮助, 再加上以下这些信息:

1. 你做了什么
2. 你希望的结果是什么
3. 实际上的结果是什么

感谢您帮助我们改进这个程序.

如何创建一个有用的跟踪栈

如果Org报出了一个i额你不明白的出错信息,你可能发现了BUG. 报告这个BUG的最好方法是提供一个跟踪栈(backtrace). 跟踪栈使用内置的调试信息来收集一些信息,这些信息包括错误发生的地点和方式. 下面是提供一个有用跟踪栈的步骤

  1. 重新加载未编译的所有Org mode的Lisp源文件. 如果错误是在未编译的脚本中产生时,跟踪栈能够提供多得多的信息. 要做到这一步,执行
    C-u M-x org-reload RET
        

    或者在Emacs菜单上选择’Org -> Refresh/Reload -> Reload Org uncompiled’

  2. 在’Options’菜单中选择’Enter Debugger On error’(如果是使用XEmacs,需要在’Troubleshooting’子菜单中选择此项).
  3. 复现错误,别忘了记录操作的每个步骤
  4. 当错误产生了,一个名为*Backtrace*的缓存区会显示出来,保存这个缓存区到文件中(一般是用C-x C-w命令)然后附加在你的错误报告中.

手册中的排版约定 : 手册中的排版约定

Org使用三种类型的关键字:TODO关键字,标签和属性名称. 在该手册中我们使用如下约定:

TODO
WAITING

TODO关键字全部大些,即使它们可以用户随意定义的.

boss
ARCHIVE

用户自定义的标签使用全小些;内置的标签具有特定的意义,使用全大些形式

Release
PRIORITY

用户自定义的属性使用首字母大些;内置属性有特定意义的,使用全大些形式.

该手册列出特定功能的键序列和相应的命令. Org mode经常使用相同的键序列来在不同的上下文中触发不同的功能. 绑定到这些键序列的命令都有一个通用的名称,比如’org-metaright’. 在该手册中,我们会尽可能的给出通用命令内部调用的函数名称. 例如,在文件结构的章节上按下’M-<right>’会被指明调用的是’org-do-demote’程序,而在表标题上按下相同的键序列时,我们会指明调用的是’org-table-move-column-right’.

如果你愿意,你可以编译这份手册使之不带有命令名称,方法是在’org.texi’中取出’cmdnames’标志.

文档结构

Org是基于Outline-mode的,它提供了大量的命令来编辑文档的结构.

大纲 :Org是基于Outline-mode的

Org的实现是基于Outline-mode的.Outline运行文档按照分级结构的方式来组织,这种方式(至少对于我来说)是用来展示记录和想法的最佳方式.通过折叠(隐藏)绝大部分的文档内容而只显示文档的大致结构和正在编辑的这一部分内容,一个文档结构的总览被完美地展示出来. Org极大地简化了对大纲的操作,它把整个显示/隐藏功能都通过一个命令来完成:’org-cycle’,这个命令被绑定到了<TAB>键上.

标题 :如何排版Org的树状标题

标题定义了大纲树的结构. Org的标题以一个或多个星号开头,向左对齐[fn:4]. 例如:

* Top level headline
** Second level
*** 3rd level
,    some text
*** 3rd level
,    more text

* Another top level headline

有些人觉得太多的星号眼花缭乱,它们可能更喜欢Outline-mode使用空格加星号的格式作为标题的开始标识.一个更简洁的大纲显示中描述了如何配置.

在子树的末尾的空行,被认为是子树的一部分,它会随着子树的折叠而被隐藏. 然而,如果你放了两个空行,那么在折叠这个子树的时候,还会有一个空行是可见的,这样做的目的常常是为了构造分割的视图. 要改变这种行为,需要配置变量’org-cycle-separator-lines’

可见性的转换 :显示和隐藏,很简单

Outline使得隐藏缓存区中的一部分文本成为可能. Org仅仅使用两个命令来切换缓存区的可见性,这两个命令被绑定到了’<TAB>’和’S-<TAB>’上.

<TAB> (org-cycle)
子树循环:以下面的循环状态来切换当前子树的状态
	,-> FOLDED -> CHILDREN -> SUBTREE --.
	'-----------------------------------'

为了执行子树的切换,光标位置必须在子树的标题上[fn:5]. 若光标在缓存区的最前端,而这第一行又不是标题,那么<TAB>实际上执行的是’全局循环’(具体情况见下文)[fn:6]. 同样的,如果使用的是带前缀参数的<TAB>(C-u <TAB>),调用的也是’全局循环’

S-<TAB> / C-u <TAB> (org-global-cycle)
全局循环:使整个缓存区在在不同状态间切换
	 ,-> OVERVIEW -> CONTENTS -> SHOW ALL --.
	'--------------------------------------'

若再S-<TAB>前加了一个数字前缀N,那么CPMTEMTS一直到第N个层次的内容都会显示出来. 需要注意的是,若是在编辑表格中,S-<TAB>的作用是跳到上一个域.

C-u C-u <TAB> (show-all)

显示所有信息,包括’抽屉’内的信息

C-c C-r (org-reveal)

显示光标周围的上下文,也就是显示当前条目,以及所有上层标题. Useful for working near a location that has been exposed by a sparse tree command (see section Sparse trees) or an agenda command (see section Commands in the agenda buffer). With a prefix argument show, on each level, all sibling headings. With a double prefix argument, also show the entire subtree of the parent. (TODO 真没看懂什么意思,在实验C-c C-r的时候我的Org居然没反应…)

C-c C-k (show-branches)

展开所有子树的标题,如果只有一个子树,那么内容也显示出来.

C-c C-x b (org-tree-to-indirect-buffer)

把当前子树显示在indirect buffer中[fn:7]. 如果加了一个前缀参数N,它会向下进入地N层子树并在indirect buffer中显示该子树. 如果N是负数,那么就是向上进入N层的父节点. 如果命令执行前加了C-u前缀,则打开新的indirect buffer,而不会关闭之前打开的indirect buffer.

C-c C-x v (org-copy-visible)

拷贝文本块中的可见文本到kill ring中

当Emacs第一次打开一个Org文件时,全局状态为OVERVIEW,也就是说,只有顶层的标题是可见的. 这个行为可以通过配置’org-startup-folded’变量来改变.或者可以在文件的任何地方添加下面所列出的任何一句,Emacs就会根据这句配置信息自动设置初始的状态.

#+STARTUP: overview
#+STARTUP: content
#+STARTUP: showall
#+STARTUP: showeverything

此外,任何带有’VISIBILITY’属性名的条目(参考属性与列)会相应地按照该属性值来设置可见性. 该属性的有效值可以使’folded’,’children’,’cotent’和’all’

C-u C-u <TAB> (org-set-startup-visiblity)
重置该buffer的可见性为该buffer在启动时的可见性,也就是说根据buffer的’startup’选项和各个单独条目的’VISIBILITY’属性来重新设置整个buffer的可见性.

移动 :跳转到其他标题

下面的命令跳转到buffer中的其他标题

C-c C-n (outline-next-visible-heading)
下一个标题
C-c C-p (outline-previous-visible-heading)

上一个标题

C-c C-f (org-forward-same-level)

同一级的下一个标题

C-c C-b (org-backward-same-level)

同一级的上一个标题

C-c C-u (outline-up-heading)

回到上一级标题

C-c C-j (org-goto)

跳转到其他位置的同时不改变当前大纲的可见性. 在一个临时buffer中显示文档的结构,在这个临时buffer中你可以使用下面的快捷键来定位:

	<TAB>           切换可见性
	<down> / <up>   下一个/上一个可见的标题
	<RET>           选定当前位置
	/               在树中作一个匹配查询
	如果你关掉了org-goto-auto-isearch选项,下面这些快捷键才可用
	n / p           下一个/上一个可见的标题
	f / b           同级别的上一个/下一个标题
	u               回到上一级标题
	0-9             数字参数
	q               退出这个临时buffer

参见变量’org-goto-interface’

结构编辑 :改变标题的次序和层次

M-<RET> (org-insert-heading)
插入一个与当前位置同级别的新标题. 如果光标位于一个普通的列表项,新的列表项被创建(参见普通列表). 要强制创建新标题,则需要使用前缀参数. 如果在一行的中间执行这个命令,那么这一行会被分割成两行,光标到行尾的内容会成为新的标题[fn:8]. 如果实在一个标题的开头执行这个命令,那么新标题会天骄到当前行的前面. 如果是在所有行的前面执行这个命令,那么就创建了一个新的文件头. 如果是在折叠起来的子树末尾使用这个命令(也就是说,是在标题末尾的省略号之后),那么与当前标题类似的标题会被插入到这个子树的末尾.
C-<RET> (org-insert-heading-respect-content)

类似与M-<RET>,不同之处在于,当在当前标题后增加一个新标题时,M-<RET>会在当前标题的内容前增加一个新标题(内容成为这个新标题的内容),而C-<ERT>则在内容后增加一个新标题(内容还是原标题的内容). 这个命令在条目的任何地方都是一样的行为.

M-S-<RET> (org-insert-todo-heading)

插入一个与当前标题同级别的TODO事项. 参见变量’org-treat-insert-todo-heading-as-state-change’

C-S-<RET> (org-insert-todo-heading-respect-content)

插入一个与当前标题同级别的TODO事项, 与C-<RET>类似,新的标题会插在当前子树的后面.

<TAB> (org-cycle)

在一个未输入内容的标题上,第一次按<TAB>,这个标题成为了上一个标题的子标题,再按一下<TAB>,这个标题的级别变成了上一个标题的父标题,然后每按一次<TAB>级别就上升一级,一直到最高级.到了最高级再按一次<TAB>,又会回到初始的级别.

M-<left> (org-do-promote)

提升当前标题一级

M-<right> (org-do-demote)

降低当前标题一级

M-S-<left> (org-promote-subtree)

提升当前子树一级

M-S-<right> (org-demote-subtree)

降低当前子树一级

M-S-<down> (org-move-subtree-up)
上移当前子树(与同级别的上一个子树交换位置)
M-S-<down> (org-move-subtree-down)
下移当前子树(与同级别的下一个子树交换位置)
C-c C-x C-w (org-cut-subtree)

剪切当前子树,也就是说把当前子树从buffer移到kill ring中. 加一个前缀参数N,会剪切N个连续的子树.

C-c C-x M-w (org-copy-subtree)

把当前子树拷贝入kill ring中, 加上一个前缀参数N,会拷贝N个连续子树

C-c C-x C-y (org-paste-subtree)

从kill ring中粘贴子树. 该操作会自动更改被粘贴子树的级别以便它能够使用粘贴的位置. 你也可用在粘贴时就指定好级别,方法有两个,一个是在粘贴命令前加一个数字前置参数,第二种方法是在已经标示好的标题(比如’****’)后粘贴子树.

C-y (org-yank)

根据变量’org-yank-adjusted-subtrees’和’org-yank-folded-subtrees’的值,org-yank可用很智能地用与命令C-c C-x C-y一样的方式来粘贴折叠起来的子树. 在缺省的配置中,org-yank不会调整级别,并且除非会把原先可见的文本折叠起来,否则被粘贴的子树会子的那个被折叠起来. 任何前缀参数会让这个命令强制执行一个带着前缀参数的普通的yank操作. 要强制执行普通yank的一个好方法是按下C-u C-y. 如果在yank之后,你紧接着执行yank-pop命令,就会yank当前kill-ring前一个的内容,而且不会作调整和折叠动作.

C-c C-x c (org-clone-subtree-with-time-shift)

拷贝一堆的同级副本. 你可以一次性拷贝多个同级副本,并且你若拷贝的条目中含有时间戳信息的化,你还可以定义时间戳信息如何变化. 这项功能十分有用,例如,当你要分配任务来准备一系列的课程时. 更多细节参见命令’org-clone-subtree-with-time-shift’的文档字符串.

C-c C-w (org-refile)

转存指定条目或文本块到另一个地方.参见章节转存记录.

C-c ^ (org-sort-entries-or-items)

对同级条目进行排序. 如果选择了一块文本块,所有文本块中的条目都会被排序. 否则当前标题下的子节点进行排序. 该命令会提示你选择排序的方法,可选择的方法有按字母顺序排序,按数字顺序排序,按时间排序(创建时间,规划时间,最后期限),按优先级排序,按TODO的关键字排序(需预先在配置中定义好关键字的排序顺序),按属性值排序. 你也可以采取逆排序的方式排序. 你甚至可以提供自己的函数来对其他的关键字进行排序. 如果加了C-u前缀,排序是大小写敏感的.

C-x n s (org-narrow-to-subtree)

缩减buffer只显示当前的子树的内容

C-x n s (org-narrow-to-block)
缩减buffer只显示当前块的内容
C-x n w (widen)

回复被缩减的buffer

C-c * (org-toggle-heading)

该命令把正文转变为一个标题(正文在它的位置成为上一个标题的一个子标题). 也会把一个标题转变为正文. 如果选择了一个文本块,那么文本块中的所有行都变成标题. 如果该文本块中第一行是一个item(什么意思??),那么只把这个item转换为标题. 最后,如果文本块中第一行是一个i额标题,那么该文本块中所有的标题都变成正文.

当对一个选定的文本块(Transient Mark mode)作升级/降级操作时,会影响到文本块中所有的标题. 要选择一个包含很多标题的文本块,最好是把point和mark都放在行首,mark放在第一个标题的行首,point放在要改变的最后哪个标题的下一行的行首. 需要注意的是,如果光标在表格内部(参见表格). Meta-光标键的操作有不同的作用.

Sparse树 :与情景有关的匹配

Org-mode的一个很重要的功能是它可以根据一系列的条件,将一棵大纲树中所匹配出来的一部分形成一棵sparse树,也就是说,整个文档都会尽可能的折叠起来,唯独所匹配的信息和上级标题是可见的[fn:9]. 你只要尝试以下,就立刻能够明白它是怎么工作的.

Org-mode有很多命令可以创建Sparse树,所有这些命令都可以通过dispatcher来触发.

C-c / (org-sparse-tree)
它会提示你输入一个额外的快捷键来选择特定的sparse树的创建命令
C-r / r (org-occur)

提示输入一个正则表达式,然后显示所有匹配的sparse树. 如果有标题匹配,那么只有这个标题可见. 如果是正文匹配,那么标题和正文同时可见. 为了提供最低限度的上下文信息,所有上层标题和紧跟者匹配部分的标题都会被显示. 每个匹配的部分都被高亮; 若这是你对文档进行编辑动作,则高亮会消失[fn:10]. 同样你也可以通过C-c C-c来取消高亮. 如果执行C-u C-c / r则以前匹配的高亮会被高持,这样多次调用这个命令的结果就被保存了下来.

M-g n 或者 M-g M-n (next-error)

跳到当前buffer中匹配的下一个sparse树

M-g p 或者 M-g M-p (previous-error)

跳到当前buffer中匹配的上一个sparse树

对于那些常用的sparse树查询,你可以在变量’org-agenda-custom-commands’中定义快捷键,直接执行这些sparse树查询. 然后就可以在agenda dispatcher中使用这些快捷键来快速查询了.例如

(setq org-agenda-custom-commands
      '(("f" occur-tree "FIXME")))

会定义一个键序列为’C-c a f’的快捷方式,这个快捷方式会通过匹配字符串’FIXME’来创建sparse树.

其他的sparse树命令(例如通过TODO关键字,标签或者属性来查找)会在手册后一点的位置提到.

要打印出sparse树,你可以使用emacs命令’ps-print-buffer-with-faces’,这个命令不会把不可见部分给打印出来[fn:11]. 或者你可以用命令’C-c C-e v’把可视化的部分导出到文档中,然后打印导出文档.

纯文本列表 :条目中的附加结构

在大纲树的正文内容中,手工排列好的列表被认为是带有一定结构的. Org提供了一种方式来创建带复选框的列表(参见复选框),它提供工具来编辑这种列表,并且在导出时(参见章节导出)能够解析并且格式化这些列表.

Org支持有序列表,无序列表和描述列表

  • 无序列表,以’-‘,’+’或者’*’[fn:12]开头
  • 有序列表以数字开头,后接句号或者右括[fn:13](像这样’1.’,’1)’)[fn:14]. 如果你想让列表以其他值作为初始值开始计数,需要以类似[@20]这样的文本开头[fn:15]. 这样的用法可以用在列表的任何一项上(而不需要仅仅是第一项),以强制从指定数字顺序开始.
  • 描述列表是一种无序列表,它包含’::’作为分隔符来分割术语和描述.

同一个列表中的列表项必须有相同的缩进. 尤其当一个有序列表的计数达到了’10’的时候,那么这两位的计数必须与列表中的其他计数左对齐. (一个列表项可以是多行的.)当一个列表项的下一行的缩进与该列表项本身的缩进相等甚至跟少时,才表示该列表项结束了.

当所有的列表项结束时,一个列表才被认为是结束了的,这意味在有一行的缩进等于或者小于列表第一项的缩进前,该列表都没有结束. 当然,你也可以用两个空白行[fn:16]来强制结束列表. 这种情况下,所有的列表项都被关闭了.下面是一个例子.

** Lord of the Rings
   My favorite scenes are (in this order)
   1. The attack of the Rohirrim
   2. Eowyn's fight with the witch king
      + this was already my favorite scene in the book
      + I really like Miranda Otto.
   3. Peter Jackson being shot by Legolas
      - on DVD only
      He makes a really funny face when it happens.
   But in the end, no individual scenes matter but the film as a whole.
   Important actors in this film are:
   - Elijah Wood :: He plays Frodo
   - Sean Austin :: He plays Sam, Frodo's friend.  I still remember
     him very well from his role as Mikey Walsh in The Goonies.   

Org能正确地对这些列表进行filling和warpping调整[fn:17], 而且能够以一种恰当的方式导出这些列表(参见导出). 由于缩进决定了这些列表的结构,许多像#+BEGIN_…这样的block可以通过缩进来表明它们是属于哪一个列表项的一部分的.

如果你觉得为子列表使用不同的标示(而不使用当前列表项的标示)可以增加可读性,你可以自定义变量’org-list-demote-modify-bullet’. 如果你想改变缩进程度,自定义变量’org-list-indent-offset’

当光标处于某列表项的第一行(即带有列表项标示的那一行),可以用下面这些命令来对列表项进行操作. 其中有些命令暗含某些规则来保证列表结构是正确的. 如果你想让这些命令妨碍了你,可以通过配置’org-list-automatic-rule’来禁用其中的某些命令.

<TAB> (org-cycle)
列表项可以像标题一样具有折叠的功能. 正常情况下,只有当光标处在plain list item上时才能进行这种折叠操作. 欲了解更多的细节,请看变量’org-cycle-include-plain-lists’. 如果该变量的值为’integrate’. plain list items会被当成是低层次的标题看待. 而*号和数字缩进层次则决定了把它当成几级标题来看待. 列表项的等级总是要低于真正的标题, 然而列表的等级制度与标题的等级制度是完全分开的. 在一个新的还未写内容的列表项上,第一次按<TAB>会把它变成上一个列表项的子项.再按一次<TAB>会上升一个层级,并且下去直到最顶列表项的层级,再按一次则返回最原始的层级位置.
M-<RET> (org-insert-heading)

插入新列表项到当前层级. 若在前面加了前缀参数,则强制插入的是标题(参见结构编辑). 如果在一个列表项的中间位置执行这条命令,这个列表项会被分为2部分,而第二部分则变成了一个新的列表项[fn:18]. 如果在列表项的内容前执行这个命令,则新列表项插入在当前列表项前.

M-S-RET

插入带复选框的列表项(见复选框)

S-up 和 S-down

跳转到当前列表的上一个/下一个列表项上去[fn:19],不过该命令只有在’org-support-shift-select’被关闭的情况下才能用. 如果不是的话,你可以使用段落跳转命令代替,快捷键为C-<up>和C-<down>

M-up 或 M-down

向上或者向下移动列表项及其子项[fn:20](与上一个/下一个同缩进的列表项交换). 如果列表是有序列表,会自动重新计算序号.

M-S-left 和 M-S-right
减少/增加列表项(联通其子项)的缩进. 在第一次开始改变缩进时Org就会记住缩进的范围,并且在以后的多次缩进中都以次范围为准进行缩进,即使在缩进过程中可能会形成新的继承体系也不管. 如果你想在新的继承体系上进行缩进,那么你可以移动以下光标或者其他方法来先中端命令链,重新开始新的缩进过程.

作为一种特殊的情况,在列表的第一个列表项上用这个命令会移动整个列表. 你可以通过配置’org-list-automatic-rules’来禁止这种行为. 一个列表的总体缩进对列表后面的文本并无影响力(什么意思??)

C-c C-c

如果所在的列表项是带复选框的(参见复选框),那么就会转换复选框的状态. 在任何情况下,该命令都会校验整个列表序号和缩进的一致性.

C-c -
循环更改整个列表的列表项标志(对于无需列表:’-‘,’’,’*’;对于有序列表:’1.’,’1)’),更改的具体方式依据’org-plain-list-ordered-item-terminator’,列表的类型和列表项的位置来决定的[fn:21]. 如果加了一个数字前缀N,就会选择’,*,1.,1),-‘中第N个标识作为列表项的标识. 如果在调用该命令时选择了一个文本块,那么整个文本块会转换成一个列表项. 如果加了前缀参数,那么文本块中所有的行各自转换成为列表项. 如果第一行依据是一个列表项,那么文本块中所有的列表项标识都被删除. 最后,即使没有选择文本块,一个普通的文本行也会转换成列表项.
C-c *

把一个普通列表转换为标题(这样它就原地转换为了一个子标题). 更详细的扩展参见结构编辑.

C-c C-c *

把整个列表转换成当前标题下的子树. 带复选框的列表项(参见复选框)会转换成TODO(复选框没被选上)或者DONE(复选框被选上)关键字.

S-left 或 S-right

当光标处于列表项的任意位置上时,这个命令也会起到循环转换列表项标志的作用. 具体怎么转换依赖于’org-support-shift-select’

C-c ^

对列表进行排序. 你会被提示输入排序方法,有按数字排序,按字符排序,按时间排序或自定义方法排序.

抽屉 :收缩起所有的资料

有时候你想记录下一项事务的某些信息,但是这些信息在一般情况下是没必要显示出来的. 为了实现这个目的,Org mode提供了drawers功能. drawers需要在变量’org-drawers’[fn:22]中进行配置. Drawers看起来就像这样:

** This is a headline
,   Still outside the drawer
,   :DRAWERNAME:
,   This is inside the drawer.
,   :END:
,   After the drawer.

无论在标题上如何切换可见性(参见切换可见性),drawer都是收缩为一行显示的. 要看drawer内的信息,你需要移动鼠标到drawer这一行,然后按<TAB>键. Org-mode使用名为’PROPERTIES’的drawer来存放属性(参见属性与列), 你也可以把状态改变记录(参见跟踪TODO状态变化)和计时时间(参见记录工作时间)存放在名为’LOGBOOK’的drawer中. 如果你想把除了状态变化信息之外的一段记录也存放到名为’LOGBOOK’的这个drawer中,使用

C-c C-z
添加一个带有时间戳信息的记录到名为’LOGBOOK’的drawer中

区块 :折叠的区块

Org-mode使用begin…end块来实现很多功能,比如引入源代码(参见文学化例子),记录计时信息(参见记录工作时间). 在这些区块的第一行上按TAB键可以折叠/扩展该区块. 你也可以在设置在启动时自动折叠所有的块,方法是配置变量’org-hide-block-startup’或者在每个文件加上

#+STARTUP: hideblocks
#+STARTUP: nohideblocks

注脚 :如何用Org标签定义注脚

Org-mode支持创建注脚. 与’footnote.el’包相反,Org-mode中的注脚功能是专门设计在大型文档来使用的,而不仅仅是用在类型email这样的一次性文件上的. org-mode中注脚的基本语法类似于’footnote.el’中的语法,即,要在段落中定义一个注脚,它需要顶格(不能有缩进)以方括号作为注脚的标记. 如果你需要在注脚内分段,使用LaTeX语法’\par’. 要定义注脚引用,只需要简单的在文本中用方括号做一个标记. 例如

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

Org-mode会把’footnote.el’中基于数字的语法扩展为可以为注脚命名并且可以选择给注脚提供内部定义. 使用纯数字作为注脚标注(footnote.el就是这样作的)是为了提供向后兼容性,但是这种方式不鼓励使用,因为这种方式可能会与LaTeX snippets(参见内嵌LaTeX)冲突. 下面列举几种有效的注脚引用:

[ 1 ]
一个纯数字的注脚标记. 与’footnote.el’兼容,但是不推荐使用,因为像’[ 1 ]’这样的东西,很可能是code snippet的一部分.
[ fn:name ]

一个带有名字的注脚引用,这里name是一个唯一的标签.如果是自动创建的注脚引用的化,则会是一个数字.

[ fn:: This is the inline definitiion of this footnote ]

这是一个类似LaTeX的匿名注脚,其中注脚的定义直接放在引用的位置.

[ fn:name:a definition ]
这是一个带有名字的自定义的注脚. 由于Org-mode允许从多处引用到同一个说明,你可以使用[ fn:name ]来创建更多的引用.

注脚标记可以被自动创建,你也可以自定义标记自动创建时的名字. 这是由变量’org-footnote-auto-label’变量和变量相应的’#+STARTUP’关键字来决定的. 欲了解详情请查看该变量的文档字符串.

下面这些都是操作注脚的命令

C-c C-x f
注脚行为命令

当光标位于注脚引用处,该命令会跳转到注脚定义处. 若光标处于注脚定义处,跳转到(第一个)引用处.

否则,创建一个新的注脚. 根据变量’org-footnote-define-inline[fn:23]’的不同,该注脚的定义可能是作为引用的一部分,会放在文本中, 也可能放在另外的其他位置,这个位置由变量’org-footnote-section’决定.

当使用带前置参数的方式调用该命令, 会显示出一个附加选项菜单供你选择:

s   以引用顺序为依据对注脚的定义进行排序. 在编辑过程中,Org不会对注脚的定义进行排序操作. 如果你向对这些注脚的定义进行排序,使用这个命令,在对注脚定义进行排序的同时,也会根据'org-footnote-section'来移动整个条目. 用户可以通过配置变量'org-footnote-auto-adjust'来实现在每次插入/删除一个注脚后自动对注脚定义进行重新排序.
r   对类型fn:N这样的以简单数字命名的注脚进行重新编号. 可以通过配置变量'org-footnote-auto-adjust'来实现每次插入/删除一个标注就自动对标注进行重新编号.
S   先执行r操作,然后执行s操作
n   标准化所有的标准,方法为先收集所有的标注定义(包括自定义的标注定义)并移动到一个特定的区域中,然后按顺序对这些定义进行编号. 那些标注引用随后也会转换为相应的数字. 这常常是在完成一篇文档前的最后一个步骤(例如,要发送email时). 在导出文档时,exporter会自动作这一步.或者当触发类似message-send-hook时,类似的动作也会自动触发.
d   删除当前位置的标注,连同所有的标注定义和标注引用
    

根据变量’org-footnote-auto-adjust[fn:24]’的值,可以设定每插入或删除一个注脚后,自动重编码和排序文档中的所有注脚.

C-c C-c

当光标位于注脚引用处时,跳转到注脚定义处. 若光标处于注脚定义处,则跳转回注脚引用处. 若在标注位置上用带前置参数的方式调用该命令,则弹出一个与C-c C-x f一样的菜单.

C-c C-o 或 鼠标左键 或鼠标右键

注脚标签也是注脚定义与注脚引用相互之间的一种链接,你可以使用跳转链接的一般命令来在注脚定义/引用间相互跳转.

Orgstruct的minior模式 :在Org之外进行结构编辑

如果你喜欢Org-mode编辑结构和格式化列表时的这种直接了当的感受,你可能希望在其他mode下(比如Text-mode或者mail-mode)也能使用这些命令. 这时你可以使用名为’orgstruct-mode’的minor mode. 使用’M-x orgstruct-mode’来切换mode. 如果你想在默认情况下启用’orgstruct-mode’,例如设置在Message-mode下默认启用该mode,可以在配置文件中添加下面中的任一句

(add-hook 'message-mode-hook 'turn-on-orgstruct)
(add-hook 'message-mode-hook 'turn-on-orgstruct++)

‘orgstruct-mode’被激活后,当光标在一行(对org来说)看起来像是标题或列表项的第一行的文本行上时,大多数的结构编辑命令都可以被使用,即使在major mode原本定义的功能键跟’orgstruct-mode’提供的功能键有冲突时,也一样. 如果光标所在行看起来不是那种特殊的行,Orgstruct mode不会有任何作用,就跟没有开启Orgstruct mode一样. 若你使用的是’orgstruct++-mode’,Org也会在major mode中引入缩进和填充设置,并且会探测列表项第一行后面的列表项内容.

表格

Org自带一个快速而且直观的表格编辑器. 借助Emacs的’calc’包(参见<Gnu Emacs calculator manual>中的’Top’部分)甚至可以具备类似电子表格的计算能力.

内置的表格编辑器 :编辑简单的表格

Org可以很容易的使用纯文本来格式化表格. 任何以’|’为非空白字符开头的行都被认为是表格的一部分. ‘|’也是列的分隔符[fn:25].一个表格看起来类似于这样:

,| Name  | Phone | Age |
,|-------+-------+-----|
,| Peter |  1234 |  17 |
,| Anna  |  4321 |  25 |     

每次在表格内按<TAB>,<RET>或’C-c C-c’都会自动对表格进行重排. <TAB>也使光标移动到下一个域(<RET>使光标移动到下一行)并且会在表格的最后一行或者在水平线之前的位置上添加一行新行.表格的缩进是由第一行来决定的. 任何以’|-‘开头的行都被认为是水平分割行,并且在下一次表格重排时会扩展到整个表格的长度. 所有要创建上面的表格,你只需要键入

,|Name|Phone|Age|
,|-    

然后按下<TAB>来对齐表格并且开始在表格域内进行填充操作. 更快的操作是输入”|Name|Phone|Age”然后紧接着输入’C-c <RET>’.

当在表格域内输入文本时,Org以一种特殊的方法来处理<DEL>,<Backspace>,和所有的字符键,这种方法保证了插入和删除操作可以避免对其他域产生影响. 另外,如果是在光标通过<TAB>,S-<TAB>或<RET>的方式移动到新表格域后立即输入,那么新表格域中的文本会被自动清空. 如果这种行为对你产生了困扰,可以配置变量’org-enable-table-editor’和’org-table-auto-blank-field’来取消这种行为.

  • 创建和转换命令
    C-c | (org-table-create-or-convert-from-region)
    转换选定域为表格. 如果每个行都包含了至少一个TAB键,那么该函数假设选定域的值是以tab键作为分隔符的. 如果每一行都包含了一个逗号,那么选中域被假设为是CSV文件内容. 如果即没有TAB,也没有逗号,那么就认为选中域是以空格为分隔符的. 你可以使用前置参数来告诉函数使用哪种分隔符:C-u使用CSV格式,C-u C-u使用TAB为分隔符,前置参数N标示至少N个连续的空格或TAB键作为分隔符.

    如果没有选定域,这个命令会创建一个空的Org表格. 至少它比输入”|Name|Phone|Age<REt>|-<TAB>”这样来的简单.

  • 重对齐和表格域之间的移动
    C-c C-c (org-table-align)
    对表格进行重对齐操作但不移动光标的位置
    <TAB> (org-table-next-field)

重对齐操作,光标移动到下一个域中. 如果需要的话创建一个新行.

S-<TAB> (org-table-previous-field)

重对齐操作,光标移动到上一个域中.

<ERT> (org-table-next-row)

重对齐表格,并且光标移到下一行. 如果需要的话会新键一行. 若光标在一行的开头或末尾,<ERT>也会新建一行,因此该功能可以用来分割表格.

M-a (org-table-beginning-of-field)

移动到光标当前域的开头位置,或者(若已经在当前域的开头位置)上一个域的开头位置

M-e (org-table-end-of-field)

移动到光标当前域的结尾位置,或者(若已经在当前域的结尾位置)下一个域的结尾位置

  • 列和行的编辑
    M-<left> (org-table-move-column-left)
    移动当前列到左方(与左列交换位置)
    M-<right> (org-table-move-column-right)
    移动当前列到右方(与右列交换位置)
    M-<up> (org-table-move-row-up)

移动当前行到上方(与上行交换位置)

M-<down> (org-table-move-row-down)

移动当前行到下方(与下行交换位置)

M-S-<up> (org-table-kill-row)

删除当前行或水平分隔行

M-S-<down> (org-table-insert-row)

在当前行上面插入一新行. 如果加上前置参数,就在当前行下方插入新行.

C-c - (org-table-insert-hline)

在当前行下面插入一新水平分隔行. 如果加上前置参数,就在当前行上方插入新水平分隔行.

C-c <RET> (org-table-hline-and-move)

在当前行下方插入一水平分隔行,并且移动光标到该分隔行的下一行

C-c ^ (org-table-sort-lines)

对当前块的表格行进行重新排序. 光标的位置指明根据哪一列来排序, 排序的范围就是上下两个最近的水平分隔行之间所包含的行,或者是整个表格. 如果光标处于第一列的前面,你会被提示需要输入按照哪一列来进行排序. 如果存在一个被选定的块,那么文本块的标记位置就指定了要排序的起始行,并且根据标记所在的列来进行排序,而光标所在的列(包括该列)为要排序的结束行. 该命令会提示您输入排序的类型(按字母排序,按数字排序或这按时间排序). 当该命令带有前置参数的时候,按字母排序是大小写敏感的.

  • 区域
    C-c C-x M-w (org-table-copy-region)
    从表格中拷贝一个矩形区域到粘贴板. 光标所在的位置和标记的位置决定了矩阵的边界. 如果没有选定的区域,就把整个当前域拷贝到粘贴板中. 该操作会忽略水平分隔行.
    C-c C-x C-w (org-table-cut-region)

拷贝表格中的矩形区域的内容到剪贴板,并且对该矩形其余进行填空操作.因此这其实是个剪切操作

C-c C-x C-y (org-table-paste-rectangle)

粘贴矩形区域内容到表格中. 该区域的左上角放置在当前域. 所有涉及到的域都会被覆盖掉. 如果矩阵不能合适地放到当前表格中,那么当前表会根据需要扩大. 该操作会忽略水平分隔行的存在.

M-<RET> (org-table-wrap-region)

以光标位置为界限分割当前域,并且把剩下的部分移动到下一行. 如果存在已选定的文本块,并且光标和标记处于同一个列中,the text in the column is wrapped to minimum width for the given number of lines. 如果存在一个数字的前置参数,那么该参数会用来指定操作的行数. 如果没有选定的区域,而你又指定了前置参数,当前域会被清空,并且原先的内容会粘贴在当前域的上个域的内容后面.

  • 计算
    C-c + (org-table-sum)
    把当前列(或选定区域)的数字求总和.求和的结果会在echo区域显示,并且可以用C-y命令插入结果
    S-<RET> (org-table-copy-down)
    若当前域是空的,就会拷贝上方的第一个非空域的值. 如果当前域不是空的,则拷贝当前域的值覆盖下一行的值,并且鼠标也跟着下移. 根据变量’org-table-copy-increment’的设置,若域中的值是整数,则拷贝时会自增. 若域中的整数值太过巨大了,则该值不会被增加. 另外,若前置参数为0,则会暂时地禁止这种增加行为. 该键序列在shift-selection和相关模式中也有定义,因此可能会有冲突(参见与org-mode冲突的包)
  • 杂项
    C-c ` (org-table-edit-field)
    在另一个窗口中编辑当前域. 这在编辑显示不下内容的域时非常有用(参见列宽度与对齐). 当添加了C-u前缀时,仅仅只是把当前域的内容全部显示出来,这样就能在本地编辑该域了. 如果加了两个C-u前缀则会保持一个编辑窗口,该窗口的内容随着光标的所在域不同而动态改变. 这种模式会一直持续到光标离开表格,或者你重复输入该命令’C-u C-u C-c `’
    M-x org-table-import

把一个文件当作表格导入进来. 文件内容必须是以TAB或空格分隔的(通常从电子表格或数据库中导出的数据是可以定义为以TAB分隔的文本文件的). 该命令先插入文件内容到缓冲区内然后调用转换命令(org-table-create-or-convert-from-region)将内容为一个表格. 任何前缀参数都会被传递给转换命令作为决定分隔符的参数.

C-c | (org-table-create-or-convert-from-region)

也可以通过粘贴以tab分隔的文本到Org缓冲区的方式来导入表格.方法是,先用C-x C-x选择(也可以用其他方法)要粘贴的文本,然后使用’C-c |’命令

M-x org-tableexport

导出表格,默认是以TAB作为分隔符. 常常用来与电子表格或数据库程序作数据交换. 导出文件的格式可以在变量’org-table-export-default-format’中配置. 你也可以在子树中用属性’TABLE_EXPORT_FILE’来定义导出文件的名字和属性’TABLE_EXPORt_FORMAT’来定义导出文件的格式. Org支持将表格导出为许多格式. 导出的格式与Orgtbl radio表格的格式是一样的. 详细描述请参见’转换功能’.

如果你不喜欢Org的表格功能(因为你可能象要有记录一些以|开头的行,而不作为表格),你可以用下面的配置语句关掉该功能

(setq org-enable-table-editor nil)

这样一来,唯一可用的表格命令就是C-c C-c,该命令用来作人工的重对齐

列的宽度与对齐 :不使用自动化的设置

列的宽度是有表格编辑器自动决定的. 列的对齐方式也是由列中的值的类型来自动决定的,若值类似于数字则默认右对齐,否则默认为左对齐.

有时候,一个或多个域会由于包含了太多的文本而导致列的宽度看起来很不方便. 又或者你想象让多个列不管内容多少都保持固定的宽度. 要设置[fn:26]列的宽度, 在列的任何一个域中包含类似’<N>’这样的字符串即可. 这里N的意思代表了该列的宽度限定为N个字符长度. 下一次重排时,该列的宽度会调整为这个值.例如

|---+------------------------------|               |---+--------|
|   |                              |               |   | <6>    |
| 1 | one                          |               | 1 | one    |
| 2 | two                          |     ----\     | 2 | two    |
| 3 | This is a long chunk of text |     ----/     | 3 | This=> |
| 4 | four                         |               | 4 | four   |
|---+------------------------------|               |---+--------|

太长的域会被裁减并且以字符串’=>’结尾. 注意,此时完成的字符串还保留在缓冲区内,只不过被隐藏起来罢了. 要查看完整的文本,只需要把鼠标移到要查看的域上过一会儿,会有一个小提示窗口弹出来,里面有完整的内容. 要编辑这个域,使用命令C-c `(C-c 接着反引号). 该编辑命令会打开一个新窗口给你编辑,里面是完整的内容.输入C-c C-c完成编辑

打开一个文件时,若文件中存在缩小的列的表格,此时列中的文本不会自动进行隐藏动作.这时候的表格看起来不太好看,需要重排. 设置选项’org-startup-align-all-tables’会使org在打开文件时自动重排其中的所有表格,当然这个动作也会降低org启动的速度. 你也可以在每个文件中设置这个属性,方法为:

#+STARTUP: align
#+STARTUP: noalign

默认清空下富含数字的列是右对齐的,富含字符串的列是左对齐的,但你也可以自定义列的对齐方式,方法为在列中使用类似’<r>’,’c’[fn:27],或’<l>’这样的字符串来定义该列的对齐方式. 当然你也可以同时定义列对齐方式和列的宽度,例如’<r10>’.

当导出文档时,只包含指定格式的字符串的行会自动移除不被导出.

对列进行分组 :Grouping to trigger vertical lines

当Org导出表格时,默认是不导出表格中的竖线的,因为通常来说这不美观. 然而有时候竖线可用用来把表格划分为几个列的组(类似于水平分隔行把行划分为几个组别). 要定义列的组别,你可以使用一种特殊的行,在这一行里,第一个域只包含’/’. 接下来的域中可用包含’<’(表格这一列是一个组别的起始列),或者’>’(指示这一列是组别的结束列),或者’<>’(‘<’和’>’中间没有空格,这表示这一列自成一组). 组别之间的边界在导出时会用竖线标示出来.如下例子所示

,| N | N^2 | N^3 | N^4 | sqrt(n) | sqrt[4](N) |
,|---+-----+-----+-----+---------+------------|
,| / |   < |     |   > |       < |          > |
,| 1 |   1 |   1 |   1 |       1 |          1 |
,| 2 |   4 |   8 |  16 |  1.4142 |     1.1892 |
,| 3 |   9 |  27 |  81 |  1.7321 |     1.3161 |
,|---+-----+-----+-----+---------+------------|
#+TBLFM: $2=$1^2::$3=$1^3::$4=$1^4::$5=sqrt($1)::$6=sqrt(sqrt(($1)))

你也可以只是在想要竖线的地方插入列组的起始符号即可.例如

,|  N | N^2 | N^3 | N^4 | sqrt(n) | sqrt[4](N) |
,|----+-----+-----+-----+---------+------------|
,| /  | <   |     |     | <       |            |

名为Orgtbl的minor mode :使用minor-mode中的表格编辑器

如果你喜欢Org表格编辑器的直观操作,你也可以在别的mode(例如text-mode或mail-mode)中使用它. 名为’Orgtbl-mode’的minor mode可以实现这一点. 你可以通过’M-x orgtbl-mode’来切换该模式. 如果你想在进入特定mode(例如Message mode)时自动进入该minor mode,使用如下的配置语句

(add-hook 'message-mode-hook 'turn-on-orgtbl)

此外,通过一些配置,还可以用Orgtbl-mode实现在任意标签内包含表格. 例如,它可以实现在构建LaTeX表格时兼顾LaTeX的易用和Orgtbl-mode的能力(包含了电子表格的能力). 详细请见任意标签中的表格和列表

电子表格 :带有电子表格功能的表格编辑器

表格编辑器使用Emacs的’calc’包来实现类似电子表格的功能. 它也可以根据Emacs Lisp表达式来根据其他域中的值计算得出当前域的值. 虽然功能上类似,但是严格来说,Org的实现方式与其他电子表格的实现方式是不一样的. 例如, Org能够理解column formula(列公式)的概念,列公式会自动应用到当前列的每一个非最开头的域中,而不用在每一个域中都复制一份公式(formula). Org还提供了一个formula调试器和一个formula编辑器, 该formula编辑器会高亮公式中所引用到的域,并且可以通过方向键来移动该引用.

引用 :如何引用其他域或区域

要根据其他域的值来计算表格中的值,公式必须引用到其他域或区间. 域可用通过名称,通过绝对坐标和相对坐标用这三种方式来引用. 要确定某个域的坐标是什么,在这个域中按下’C-c ?’就会在echo区域显示出该域的坐标,也可以按下’C-c }’来切换显示坐标网格.

  • 域引用 在公式中有两种方法来引用其他域中的值. 第一种类似于其他电子表格,你可以用一个字母/数字组合起来表示一个域的引用,例如’B3’的意思是第3行的第2个域. 然而,Org更推荐[fn:28]使用另一种更加通用的表示方法,这种表示方法看起来是这样的:
    @row$column      
        

    列的可以用绝对坐标表示,类似于这样:$1,$2…$N.也可以用相对坐标表示(当前列为基准值)类似于这样:$+1,$-2,$<,$>.其中$<固定表示第一列,$>固定表示最后一列. 另外,你可以用$>>>表示从右往左数第3列

    行在计算坐标时,值计算数据行,而 不算水平分隔行(hline) .类似于列的表示方法,你可以使用绝对行数来表示,类似于@1,@2…@N,也可以用相对行数来表示,类似于@+3,@-1,@<和@>. 其中@<固定表示表格中的第一行,@>固定表示表格中的最后一行[fn:29].另外你也可用通过与hline的相对位置来引用行:@I引用第一个hline,@II引用第二个hline,一次类推. @-I引用的是当前行的上一个hline,@+I是当前行的下一个hline. 你也可以通过@III+2表示第3个hline的后2行

    $0和$0分别引用的是当前行和当前列,也就是要被计算的域的行和列. 另外,如果你忽略了引用的行或列部分,默认情况下使用当前域的行或列代替.

    Org中不带符号只含数字的引用是固定引用,也就是说如果你在两个不同的域中使用同一个引用表示法,引用的是同一个域. 而org中带符号和数字的引用是浮动引用,即相同的引用表示法可能引用的是不同的域,这取决于公式所在的那个域的位置.

    下面是一些例子:

          
    @2$3      2nd row, 3rd column (same as C2)
    $5        column 5 in the current row (same as E&)
    @2        current column, row 2
    @-1$-3    the field one row up, three columns to the left
    @-I$2     field just under hline above current row, column 2
    @>$5      field in the last row, in column 5
    
        
  • 区间引用

    你可以引用一个矩形区间,方法是指明两个域引用,并用’..’连接起来. 如果这两个域都处于同一个行,可用只使用’$2..$7’这样来代替, 但若至少有一个域处于不同的行,那么你需要对至少第一个域使用完整的@row$column格式(即引用必须以@开头,以便能够正确第解释).例如

          
    $1..$3        first three fields in the current row
    $P..$Q        range, using column names (see under Advanced)
    $<<<..$>>     start in third column, continue to the one but last
    @2$1..@4$3    6 fields between these two fields (same as A2..C4)
    @-1$-2..@-1   3 numbers from the column to the left, 2 up to current row
    @I..II        between first and second hline, short for @I..@II
    
        

    区间引用返回一个值的vector(向量),并传入Calc向量函数中执行. 区间中的空域正常来说都会被忽略掉,这样向量中就只包含了非空域(要切换这种行为,参见下面的’E’ mode).如果区域中所有的域都为空域,那么就会返回’[ 0 ]’一次来避免公式中发生语法错误.

  • 公式中的域坐标

    若要在Calc公式使用当前域的行号和列号,可用用@#和$#来表示. 在传统的Lisp公式中等价于’org-table-current-dline’和’org-table-current-column’.例如:

          
    if(@# % 2, $#, string(""))   column number on odd lines only
    $3 = remote(FOO, @@#$2)      copy column 2 from table FOO into
                                 column 3 of the current table
    
        

    对于第二个例子,FOO表格至少需要有与当前表格一样多的行. 注意:这对于大量的行操作来说是很不效率的[fn:30].

  • 命名引用 ‘$name’会被被解释成列名,参数或者常量. 可以通过变量’org-table-formula-constants’来定义全局常量,或者通过类似下面一行的方法来为某个文件定义本地常量.
    #+CONSTANTS: c=299792458. pi=3.14 eps=2.4e-6
        

    另外,在表格公式中,也可以使用属性(参见章节属性与列)来作为常量使用[fn:31]:你可以通过名为’$PROP_ Xyz’的常量来访问属性’:Xyz:’,Org会在表格所在大纲条目及其上级条目中搜索该属性. 如果你加载了’constants.el’这个包,那么Org也会使用这个包来匹配常量,这个包甚至包括自然常量(例如$h表示普朗克常量)和单位(例如$km表示千米). 列名和参数可以在一个特殊的表格行内指定,更具体描述以后再说,可以参见高级特性.现阶段所有的名字都必须以字母开头,以后可能可以以字母和数字开头.

  • 远程引用 你也可以引用其他表格中的常量,域和区间, 这些表格可以在同一个文件也可以在不同文件中. 引用的方法为
    ,        remote(NAME-OR-ID,REF)
        

    这里NAME可以是当前文件中当前表格以前所定义的表格名字. 这里表格名字可以用’#+TBLANAME:表格名字’来定义. NAME的值也可以是某个大纲条目的ID(甚至可以是其他文件中的大纲条目),这时引用的就是该条目中的第一个表格. REF是一个绝对域或绝对区间的引用(具体方法如上面所示,例如@3$3或者$somename,这些绝对引用需要确保在被引用表格中都是可用的).

Calc的公式语法 :使用Calc计算

一个公式可用是任何能够被Emacs的’calc’包所识别的代数表达式. 注意,在’Calc’中,’/’的操作符优先级要比’‘低,因此’a/b*c’会被解释为’a/(b*c)’,这一点与标准不符*. 在calc-eval(参见GNUEmacs Calc Manual中’Calling Calc from Your Lisp Programs’章节的)进行计算之前,变量替换会以之前所描述的方式发生. 公式之中的区域变量可用直接放入Calc的向量函数(例如’vmean’和’vsum’)中作为参数使用.

公式可用在分号之后附加上可选的选项模式字符串. 这种选项模式字符串由标志所组成,这些标志会在公式被执行时影响Calc和其他模式. 默认情况下,Org使用标准的Calc模式(精度为12位,角度单位为度,分数和symbolic模式为关闭状态). 然而,公式在显示时,会自动调整为(float 8)以便保持表格的紧凑. 可用通过变量’org-calc-default-modes’来配置这些默认设置

p20           set the internal Calc calculation precision to 20 digits
n3 s3 e2 f4   Normal, scientific, engineering, or fixed
              format of the result of Calc passed back to Org.
              Calc formatting is unlimited in precision as
              long as the Calc calculation precision is greater.
D R           angle modes: degrees, radians
F S           fraction and symbolic modes
N             interpret all fields as numbers, use 0 for non-numbers
E             keep empty fields in ranges
L             literal

除非你使用大整数或高精度计算式,并且需要显示浮点式数字,你可以提供一个printf格式说明字符串[fn:32]来对Calc计算并传回Org的结果进行重新格式化,而不是Calc自己作这种格式化. 下面是一些例子

$1+$2                Sum of first and second field
$1+$2;%.2f           Same, format result to two decimals
exp($2)+exp($1)      Math functions can be used
$0;%.1f              Reformat current cell to 1 decimal
($3-32)*5/9          Degrees F -> C conversion
$c/$1/$cm            Hz -> cm conversion, using ‘constants.el’
tan($1);Dp3s1        Compute in degrees, precision 3, display SCI 1
sin($1);Dp3%.1e      Same, but use printf specifier for display
vmean($2..$7)        Compute column range mean, using vector function
vmean($2..$7);EN     Same, but treat empty fields as 0
taylor($3,x=7,2)     Taylor series of $3, at x=7, second degree

Calc还包含了一个完整的逻辑操作集合. 例如

if($1<20,teen,string(""))            如果第一列(age列)比20小,则返回值"teen",否则返回空值

注意,在计算时长时,还可以使用两个特定的标志T和t,具体参见时长与时间

Emacs Lisp写成的公式 :使用Emacs Lisp来写公式

你可以使用Emacs Lisp来写公式;这在当Calc提供的函数不足与实现我们期望的操纵字符串和控制结构的功能时非常有用. 如果一个公式是以单引号后跟一个开括号开头的,则该公式被认为是Lisp形式的. 该Lisp的运算结果应该是返回一个字符串或者是数字的. 就像使用’calc’公式一样,你可以在分号’;’后面指定模式和printf格式. 使用Emacs Lisp形式,你需要关注域引用插入到form中的方式. 默认情况下,一个引用是将域中的值以字符串的形式(包括在双引号内)插入的. 如果开启了M模式,则所有的被引用元素都会被转化为数字(非数字域转化为0)并且在插入时作为Lisp数字型插入(不包含引号). 如果你提供了’L’标志,所有的域将会以字面上的方式(不包含引号)插入公式中. 也就是说,如果你想一个引用作为字符串来插入到Lisp形式的公式中,则使用双引号来包含引用表达式(例如”$3”)即可. 区域在插入时会作为一系列以空格分隔的域,这样你就可以把它们潜入list或vector符号中. 下面是一些例子–注意我们在用Lisp计算时是如何使用’N’模式的

    
Swap the first two characters of the content of column 1
  '(concat (substring $1 1 2) (substring $1 0 1) (substring $1 2))
Add columns 1 and 2, equivalent to Calc's $1+$2
  '(+ $1 $2);N
Compute the sum of columns 1-4, like Calc's vsum($1..$4)
  '(apply '+ '($1..$4));N

时长和时间的值 :如何计算工期和时间的值

如果你希望计算的是时间的值,你需要在Calc公式或Elisp公式中使用T标志

,  |  Task 1 |   Task 2 |    Total |
,  |---------+----------+----------|
,  |    2:12 |     1:47 | 03:59:00 |
,  | 3:02:20 | -2:07:00 |     0.92 |
  #+TBLFM: @2$3=$1+$2;T::@3$3=$1+$2;t
, 

输入的时长值必须是以[HH:MM[:SS]]的形式的,这里秒数是可选的. 当使用了T标志,计算出来的时长会以HH:MM:SS的形式来显示(参见上面例子的第一个公式). 当使用t标志时,计算出来的时长的显示方式是根据变量’org-table-duration-custom-format’的不同而不同的, 该变量默认单位为小时并且会以小数的形式来显示结果(参见上面的第二个公式).

Org也支持副的时长,而且数字在作加减法时会被认为是秒数.

域公式和区间公式 :给某个域或某个区间分配一个公式

要给一个域分配公式,直接输入公式,并在前面加上’:=’,例如’:vsum(@II..III)’. 当你在 光标还在域中时 按下<TAB>或<RET>或C-c C-c,公式就会被保持在该域中,并且会自动计算并把计算结果展示为域的值.

公式是统一存储在一个特殊行中的,该行是以”#+TBLFM:”开头的,并且直接就在表格的下方紧靠表格. 如果你在第3行的第4个域中输入公式,那么该公式就会类似于’@3$4=$1+$2’这样. 当使用命令插入/删除/交换了行或者列时,公式中的绝对引用(但是不包括相对引用)也会跟着改变,以保证引用还是指向与修改前同一域. 要避免这种情况发生(特别是在公式中使用了区间引用,表格的边界引用(使用@<,@>,$<,$>)或hlines引用(使用@I符号)的情况下), 你需要使用一般的编辑命令来改变表格结构.当使用一般的编辑命令来修改表结构的情况下,域引用的这种自动适配功能当然是不会发生的–这样的话,你需要自己修正公式.

除了直接在域中输入公式,你也可以使用下面这些命令

C-u C-c = (org-table-eval-formula)
为当前域分配一个新的公式. 该命令提示你输入公式(默认值为从#+TBLFM:行中获得公式),然后应用该公式到当前域并保持起来.

在公式的左侧也可以是特别的表达式,以这种方法可用为一系列不同的域分配公式. 并没有快捷方式来输入这种区间公式. 要增加这种区间公式,需要使用公式编辑器(参见编辑和调试公式)或者直接编辑$+TBLFM:行

$N= (这里N表示第几列)
列公式,对整个列生效. 这种公式如此常见以至于Org以一种特殊的方式来处理这些公式,参见列公式
@N= (这里N表示第几行)
行公式,对一行的所有域生效. @>=表示最后一行.
@1$2..@4$3=
区间公式,对所指定的矩阵区间内的所有域有效. 这可以用来分配公式给行中的一些域(但不是所有的域)
$name=

命名域,具体参见高级特性

列公式 :对整个列都生效的公式

#<<Column formulas>> 当你分配一个列公式到一个列时(使用类似$3=这样的语法),该列的所有域都会使用同一个公式,然而也会有一些例外:(i) 如果表格包含了水平分隔行hlines,任何在第一个水平分隔行之前的行都被认为是表头信息,因此就不会被列公式所改变. (ii) 如果一个域已经定义了域公式或区间公式,那么它也被列公式排除在外(即域公式和列公式的优先级高于列公式). 上诉的两个条件使得列公式很容易使用.

要分配一个列公式给某个列,直接输入公式到该列的任何一个域中,并在前面加一个-号,就像这样’$1+$2'. 当你在光标还在域的情况下按下<TAB>或<RET>或C-c C-c, 输入的公式就会作为该列的列公式而存储起来,然后经过计算,把结果在当前域(而不是当前列)中展示出来. 如果列中的某个域只包含'‘,那么该列中前一个存储起来的公式会被应用到该域中. 对于每个列来说,Org只会记住最近使用的那个公式. 在’#+TBLFM:’行,列公式看起来类似于’$4=$1+$2’这样. 列公式的左边不能是列的名字,它必须是数字形式的列引用或$>

除了输入以=开头的公式到域中,你也可以使用下面的命令来创建列公式

C-c = (org-table-eval-formula)
为该列应用一个新的列公式,然后使用该公式的计算结果显示在当前域中. 该命令会提示你输入列公式,默认值为#+TBLFM行的公式. 输入的列公式会应用到当前域中并存储起来. 如果加上一个数字前缀(例如C-5 C-c =),该命令会应用到当前列中连续N个域中.

编辑和调试公式 :修正公式

你可以在minibuffer或者直接在域中编辑一个个的公式. Org也可以准备一个包含表格中所有公式的特殊缓存区. 当对公式进行编辑时,Org在可能的情况下会转换引用为标准格式(类似于B3或者D&这样的引用). 如果你想只使用引用内部格式(类似于@3$2或者$4),请配置变量’org-table-use-standard-references’

C-c = 或者 C-u C-c = (org-table-eval-formula)
在minibuffer中编辑当前列/域的公式. 参见列公式域与区间公式.
C-u C-u C-c = (org-table-eval-formula)

为当前域重新设定一个公式(可以使域公式也可以是列公式),使用这个命令你可以直接在域中编辑公式. 与在minibuffer中编辑公式相比,这种方法的优势在于你可以使用命令C-c ?查询域的信息.

C-c ? (org-table-field-info)

当在表格域中编辑公式时,高亮公式中鼠标所在位置的域引用所引用的域.

C-c }
切换显示行列编号,using overlays(org-table-toggle-coordinate-overlays). 这些信息在每次表格重排之后都会自动更新;你也可以使用C-c C-c来强制更新信息.
C-c }
切换开启或者关闭公式调试器(org-table-toggle-formula-debugger). 具体信息参见下面
C-c ’ (org-table-edit-formulas)

打开一个特殊的缓冲区(公式编辑器),可以在里面编辑当前表格所有的公式,在这个缓冲区中,每个公式都显示一行. 如果当前域包含包含有一个激活的公式,公式编辑器中的光标会标示出它来. 当光标在这个特殊的缓冲区中时,Org会自动高亮任何光标位置的域引用所引用的域. 你可以在这个特殊缓冲区中使用下面这些命令来编辑,删除和新增公式

C-c C-c 或 C-x C-s (org-table-fedit-finish)

退出公式编辑器,并且保持修改后的公式. 如果加了C-u前缀,那么会对整个表格应用新修改的公式(表格中所有的公式都会被重新计算一遍,然后显示出来)

C-c C-q (org-table-fedit-abort)

退出公式编辑器,而不做任何修改

C-c C-r (org-table-fedit-toggle-ref-type)

对表格编辑器中的所有引用切换显示格式,在标准格式(类似于B3)和内部格式(类似于@3$2)间切换

<TAB> (org-table-fedit-lisp-indent)

美化并缩进当前光标所在的Lisp公式. 当光标所在行包含有Lisp公式时,使用Emacs Lisp的规则来格式化公式. Another <TAB> collapses the formula back again. 在open formula(开放式公式??)中,<TAB>跟在Emacs Lisp mode一样起着重新缩进的功能.

M-<TAB> (lisp-complete-symbol)

补完Lisp符号,就跟在Emacs Lisp mode中一样

S-<up>/<down>/<left>/<right>

切换光标所在的引用. 例如如果现在光标所在的引用是B3,你按下S-<right>之后,该引用变成了C3. 这对相对引用和hline引用也有效

M-S-<up> (org-table-fedit-line-up) 或 M-S-<down> (org-table-fedit-line-down)

上下移动Org buufer中行公式的test line

M-<up> (org-table-fedit-scroll-down> 或 M-<down> (org-table-fedit-scroll-up)

滚动表格所在的窗口

C-c }

显示/关闭表格中各个域的坐标 把一个域清空并不会删掉这个域的公式,因为公式实际上是保存在其他行(#_TBLFM行)-这样在下一次重新计算时,该域又会有新的值初出现. 要删掉一个域中的公式,你需要在编辑公式要求输入新公式时输入一个空回复,或者直接编辑#+TBLFM行

你可以直接编辑’#+TBLFM’行,然后在该行运行C-c C-c来对改变后的公式进行重新计算.或者也可以在表格中执行普通的重计算命令.

调试公式

当公式的计算产生错误时,域中的内容变为字符串’#ERROR’. 如果你想知道在变量替换和计算时都发生了什么以便寻找bug,你可以在Tbl菜单上打开公式调试功能然后重新对改公式计算一次(在域中按下C-u C-u C-c = <RET>).随后就会显示详细信息出来.

更新表格 :重新计算所有相关域

表格一般来说不会自动进行重计算,而是需要通过命令来触发. 要想使表格半自动地进行重计算,请参见高级特性,

要想对整个表格或者一整行进行重新计算,可用使用下面的命令:

C-c * (org-table-recalculate)
重新计算当前行,计算的方法是首先从左到右对该行的每个域都计算一次列公式,然后再当前行的域公式和区间公式.
C-u C-c * 或C-u C-c C-c

一行一行地重新计算整个表格. 任何在第一个hline之前的行都被认为是表头而排除在重计算操作之外

C-u C-u C-c * 或 C-u C-u C-c C-c (org-table-iterate)

重复对表格进行重计算,直到没有变化可以继续产生. 如果有些域的计算结果依赖于其他域的值,而这些被依赖的域的值需要在指向了一系列的计算之后才能得到的时候,这时候这项功能就很有必要了.

M-x org-table-recalculate-buffer-tables

重新计算当前缓冲区中的所有表格

M-x org-table-iterate-buffer-tables

对当前缓冲区中的所有表格进行迭代计算,以便converge(汇聚??)表与表之间的依赖关系.

高级特性 :域和列的名字,参数和自动重计算

#<<Advanced features>> 如果你想自动重计算域的值,或者你想为域和列分配名字[fn:33],你需要保留表格的第一列作存放特殊的标志字符.

C-# (org-table-rotate-recalc-marks)
使第一列的标志字符在’ ‘,’#’,’*’,’!’,’$’这几个状态之间切换. 如果存在一个激活的块,则会改变该块中所有的标志.

下面的例子是一个记录学生考试成绩的表格,里面用到了这些特性:

,|---+---------+--------+--------+--------+-------+------|
,|   | Student | Prob 1 | Prob 2 | Prob 3 | Total | Note |
,|---+---------+--------+--------+--------+-------+------|
,| ! |         |     P1 |     P2 |     P3 |   Tot |      |
,| # | Maximum |     10 |     15 |     25 |    50 | 10.0 |
,| ^ |         |     m1 |     m2 |     m3 |    mt |      |
,|---+---------+--------+--------+--------+-------+------|
,| # | Peter   |     10 |      8 |     23 |    41 |  8.2 |
,| # | Sam     |      2 |      4 |      3 |     9 |  1.8 |
,|---+---------+--------+--------+--------+-------+------|
,|   | Average |        |        |        |  29.7 |      |
,| ^ |         |        |        |        |    at |      |
,| $ | max=50  |        |        |        |       |      |
,|---+---------+--------+--------+--------+-------+------|
#+TBLFM: $6=vsum($P1..$P3)::$7=10*$Tot/$max;%.1f::$at=vmean(@-II..@-I);%.1f 

注意事项:请注意,对于这些特殊的表格来说,使用’C-u C-c ’ 来重计算表格,只对标记了’#’或’‘的行,和那些分配了公式的域生效. 列公式对当第一个域为空的行无效.

这些标志字符的意义如下所示:

’!’
该行的域中的值为列的名称,因此你可以使用引用’$Tot’来代替’$6’
’^’
这一行定义了上一行相应域的名称. 有着这种定义,任何表格中的公式可以使用’$m1’来引用值’10’. 而且如果你为这个命名了的域分配公式,该公式会被存储为’$name=…’的形式
’-’
类似于’^’,但是是为下一行的相应域定义名字的.
’$’
这一行的域可以为公式定义参数. 举个例子,如果’$’行中的某个域包含了’max=50’,则表格中的公式可以使用’$max’来引用50这个值. 参数就好像是常量一样,所不同的是它们(参数)能够根据每个表格来定义.
’#’
当在行中按下了<TAB>或<RET>或S-,TAB>,所有该标示的行中的域会自动重新计算. 另外当使用全局重计算命令(C-u C-c * )时这些行也会进行重计算,而无标示的行则对该全局重计算命令无效.
’*’
当使用全局重计算命令(C-u C-c * )时,该标志行也会进行重计算,但是该标志行并不会自动进行重计算. 当自动重计算功能会明显降低编辑效率时,该标志很有用.
无标志字符的行在使用C-u C-c * 进行重计算时并不会进行重计算. 只有标示了’#’或’*’的行才会重新计算.
’/’
不导出带有该标志的行. 对那些包含了narrowing ‘<N>’标记(缩小的’<N>’标记)或列的分组标志很有用.

最后,你可能会对使用梦幻般的’calc.el’包能实现那些功能很感兴趣, 下面是一个表格,它计算了the Taylor series of degree n at location x for a couple of functions.

,|---+-------------+---+-----+--------------------------------------|
,|   | Func        | n | x   | Result                               |
,|---+-------------+---+-----+--------------------------------------|
,| # | exp(x)      | 1 | x   | 1 + x                                |
,| # | exp(x)      | 2 | x   | 1 + x + x^2 / 2                      |
,| # | exp(x)      | 3 | x   | 1 + x + x^2 / 2 + x^3 / 6            |
,| # | x^2+sqrt(x) | 2 | x=0 | x*(0.5 / 0) + x^2 (2 - 0.25 / 0) / 2 |
,| # | x^2+sqrt(x) | 2 | x=1 | 2 + 2.5 x - 2.5 + 0.875 (x - 1)^2    |
,| * | tan(x)      | 3 | x   | 0.0175 x + 1.77e-6 x^3               |
,|---+-------------+---+-----+--------------------------------------|
#+TBLFM: $5=taylor($2,$4,$3);n3

Org-Plot :org表格绘图

通过使用’Gnuplot’http://www.gnuplot.info 和’gnplot-mode’http://cars9.uchicago.edu/~ravel/software/gnuplot-mode.html ,Org-Plot可用根据表格中的数据生成2D和3D图表. 这里有一个例子: 首先确保你安装了Gnuplot和Gnuplot mode,然后对下面的表格调用’org-plot/gnuplot’

#+PLOT: title:"Citas" ind:1 deps:(3) type:2d with:histograms set:"yrange [0:]"
,| Sede      | Max cites | H-index |
,|-----------+-----------+---------|
,| Chile     |    257.72 |   21.39 |
,| Leeds     |    165.77 |   19.68 |
,| Sao Paolo |     71.00 |   11.50 |
,| Stockholm |    134.19 |   14.33 |
,| Morelia   |    257.56 |   17.67 |

注意,Org Plot会自动把表格的标题作为生成图表的标签. 通过表格前的#+PLOT:行,你还可以定义plot的标签,类型,内容和展示. 下面列出了完整的Org-plot选项. 更多的信息和例子请参见Org-plot教程http://orgmode.org/worg/org-tutorials/org-plot.html

Plot Options

set
当绘图时,用于设置任何的gnuplot选项
title
指定plot的标题
ind
指定表格的哪一列作为x轴
deps
指定描绘哪些列,该设置的格式类似于Lisp中的list,由小括号括起来,内部用空格分隔,例如’dep:(3 4)’指定只描绘第3,4列(默认情况下,除了指明为ind的列,其他的列都会被描绘)
type
指定plot是2d还是3d还是grid的
with
对每一个要被绘制的列都插入一个指定的with选项(例如,lines,points,boxes,impulses,等等). 默认值为lines
file
如果你想将描绘输出成一个文件,指定输出文件的路径
labels
用一个列表指定各输出列的标签(默认情况下,如果列的标题村爱的话,使用列标题作为标签)
line
在gnuplot脚本中插入指定的一整行(Specify an entire line to be inserted in the Gnuplot script. )
map
当描绘类型为3d或grid时,该选项的值设为t则在描绘时描绘的是一个平面映射而不是3维图形(set this to t to graph a flat mapping rather than a 3d slope)
timefmt

指定Org-mode的时间戳格式,因为它们会被Gnuplot所解析,默认格式为’%Y-%m-%d-%H:%M:%S’

script
如果你想实现完全的自定义,你可以指定一个脚本文件(把文件名放在双引号内)来实现描绘动作. 在正真描绘之前,这个特定脚本中的每个’$datafile’会被替换成生成的数据文件的实际路径. 注意:即使你设置了这个选项,你也可能仍然需要定义plot的type,因为这个选项会影响到生成的数据文件的内容.

超链接

类似于HTML,Org提供了文件内部的链接,和文件外部的链接(可以链接到其他文件,Usenet文章,email等等)

链接的格式 :Org中的链接是什么格式的

Org会识别类似URL的链接并且把它们作为可点击的链接. 然而,Org中链接的一般形式看起来像下面这样子

[[链接地址][描述]]  或者 [[链接]]

一旦缓冲区中的链接被补完(所有的中括号都有了), Org会只显示链接中的’描述’,而不是链接的完整形式. Link会以’org-link’定义的方式高亮,默认情况下是以下划线标示起来. 你可以直接编辑链接的显示部分(当有描述部分是为’描述’部分,否则为’链接’部分). 要编辑不可见的’链接’部分,把光标放在要编辑的链接上然后按下C-c C-l

如果光标在链接的起始部分或就在链接中显示文本的后面,然后你按下<DEL>或<BACKSPACE>时,你删掉的是链接中不可见的中括号. 这样会使这个链接变得不完整,因此该链接的内部表现形式会以纯文本的方式展现出来. 再补完这个中括号又会使链接隐藏其内部结构. 要显示出所有链接的内部结构,使用菜单’org->hyperlinks->Literal links’

内部链接 :链接到同一文件的不同地方

如果链接看起来不像是URL,那么它会被认为是链接到当前文件的内部. 最重要的一个例子就是一种看起来像’[[#my-custom-id] ](中间没有空格)’的链接,这种链接会连接到’CUSTOM_ID’属性为’my-custom-id’的条目中. 这种客户化的ID在导出为HTML时很有帮助(参见导出为HTML),通过这些ID,org会自动产生许多章节间的链接. 你需要保证这些客户化的ID在文件中是唯一的.

类似于’[[My Target] ]’或’[[My Target][Find my target] ]’会在当前文件中搜索指定文本,并链接过去.

当光标处于链接上时,可以用C-c C-o或鼠标点击(参见处理链接)的方式来进入链接. 连接到客户化ID的链接会指向相应的标题. 匹配文本链接的一个比较好的方法是使用dedicated target:用两个尖括号将文本括起来. 链接标的可以放置在任何地方; 有时候把这些链接标的放置在注释行中会比较好.例如

# <<My Target>>

在导出HTML时(参见导出HTML),这些链接标的会转换为已命名的锚点,可以通过http链接[fn:34]直接定位到这些锚点的位置.

如果没有’dedicated target’存在, Org会搜索与链接文本完全一样的标题(可能也会搜索TODO关键字和标签[fn:35]). 在非Org文件中,则会搜索跟链接文本匹配的文本内容. 在上面的例子中,匹配的是’my target’.

进入一个链接会把一个mark放置仅Org自己的mark ring中. 这样你可以使用C-c &退回前一个位置. 可以多次使用该命令来退到早期记录的位置上.

Radio targets 使得可以触发纯文本形式的链接.

Radio targets

Org可以自动把普通文本中特定的文本转换为链接. 因此不需要明确地创建链接,这些特定的文本会自动创建连接到带有radio target标志的位置. Radio target包裹在三个尖括号中,就像’<<<My Target>> >(不带空格)’这样. 这个radio target使得普通文本中出现’My Target’的地方都被自动转换为链接. 只有在文档第一次加载人Emacs时,Org才会自动去扫描radio target. 在编辑时要更新target列表,可以把光标放到target上,然后安歇C-c C-c

外部链接 :类似与URL这样的链接,可以链接到全世界

Org支持连接到文件,网站,Usenet,email信息,BBDB数据库条目,IRC会议及其日志的链接. 外部链接看起来类似URL. 这些外部链接是以一个简短的标示串开头后面紧跟冒号(在冒号后面不跟空格).下面是各种类的链接的例子[fn:36]

http://www.astro.uva.nl/~dominik          on the web
doi:10.1000/182                           DOI for an electronic resource
file:/home/dominik/images/jupiter.jpg     file, absolute path
/home/dominik/images/jupiter.jpg          same as above
file:papers/last.pdf                      file, relative path
./papers/last.pdf                         same as above
file:/[email protected]:papers/last.pdf   file, path on remote machine
/[email protected]:papers/last.pdf        same as above
file:sometextfile::NNN                    file, jump to line number
file:projects.org                         another Org file
file:projects.org::some words             text search in Org file[36]
file:projects.org::*task title            heading search in Org file
file+sys:/path/to/file                    open via OS, like double-click
file+emacs:/path/to/file                  force opening by Emacs
docview:papers/last.pdf::NNN              open in doc-view mode at page
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
vm://[email protected]/folder#id      VM on remote machine
wl:folder                                 WANDERLUST folder link
wl:folder#id                              WANDERLUST message link
mhe:folder                                MH-E folder link
mhe:folder#id                             MH-E message link
rmail:folder                              RMAIL folder link
rmail:folder#id                           RMAIL message link
gnus:group                                Gnus group link
gnus:group#id                             Gnus article link
bbdb:R.*Stallman                          BBDB link (with regexp)
irc:/irc.com/#emacs/bob                   IRC link
info:org#External links                   Info node link
shell:ls *.org                            A shell command
elisp:org-agenda                          Interactive Elisp command
elisp:(find-file-other-frame "Elisp.org") Elisp form to evaluate 

要自定义Org以支持新的链接类型,参见新增链接类型

一个链接应该被两个中括号括住,并且可以包含一个描述文本,这个描述文本会代替URL显示给用户看(参见章节链接类型),例如:

,[[http://www.gnu.org/software/emacs/][GNU Emacs]]

如果描述部分是一个文件的名字或者是一个连接到图像的链接,HTML导出时(参见导出HTML)会内嵌入这个图像并显示为一个可点击的按钮. 如果链接中根本没有定义描述而定义的link是指向一个图形文件的,那么这个图形文件会被内嵌入导出的的HTML文件中.

Org也会在普通文本中查找外部链接并且把它们当做真正的链接处理. 如果link部分包含有空格(例如’bbdb:Richar stallman’),或者如果你需要明确link的结尾位置所在,你可以把它们放入方括号中.

链接处理 :创建,插入和进入链接

Org提供了多种方法来创建和跟踪链接

C-c l (org-store-link)

在创建一个连接到当前位置的链接. 这是一个全局命令(你需要自己创建绑定热键),你可以用它在任一个buffer中创建指向自己的连接. 这个被创建出来的链接可以随后插入到Org-mode的buffer中保存起来(见下文). 具体创建的是哪个类型的链接由当前buffer的类型来决定

  • Org-mode buffer 对于Org文件来说,若光标位于’<<>target>’处,则创建的链接指向该target. 否则链接指向当前的headline,同时以headline作为链接中描述部分的内容[fn:37]

    如果headline有CUSTOM_ID属性的话,会创建一个连接到该客户化ID的链接. Org会创建一个全局唯一的ID,并根据org-link-to-org-use-i的值新增一条指向该ID的链接/替换原有的自定义ID. 因此在Org buffer中使用这个命令有可能会创建两个链接,一个指向可读的自定义ID,一个指向全局唯一的链接,这个全局唯一的链接即使在原条目被移动到其他文件后也是可用的. 随后当你要把链接插入Org文件时,你需要决定插入哪个链接.

  • Email/News客户端:VM,Rmail,Wanderlust,MH-E,Gnus 在很多Emacs邮件客户端buffer使用这个命令时,产生的链接会指向当前的邮件,甚至,在某些GNUS buffer中,可用指向分组. 邮件的作者和标题会作为链接的描述信息
  • Web浏览器:W3和W3M 生成的链接连接到当前的URL,网页title作为链接的描述信息
  • Chat:IRC 对于IRC链接来说,如果你设置变量org-irc-link-to-logs的值为t,那么创建的链接指向当前会话的日志,链接的形式类似于’file:/’. 否则的话,创建的链接指向当前用户/频道/服务器,链接的形式为’irc:/’
  • 其他类型的文件 对于其他类型的文件,创建的链接指向该文件,同时链接会有一个搜索字符串(参见指向文件链接的搜索项)指向当前行的内容.
    C-c C-l (org-insert-link)

插入一个链接[fn:38].它会提示你输入一个链接,并将这个链接插入到当前的buffer中. 你可以输入上面例子中提到的任何类型的链接.随后系统会让你输入链接的描述文本并将生成的链接插入到buffer中[fn:39]. 如果在调用该命令时选中了一些文本,那么选中的文本会成为默认的描述文本呢

  • 插入存储过的链接 所有在当前会话期存储过的链接都会记录到该命令提示的历史信息中,因此,在提示符中你可以用<up>和<down>(或者M-p/n)来切换历史链接信息
  • 支持补全 如果你要插入的链接前缀类似于’http:’或’ftp:’,你可用通过按<TAB>键来自动补全.比如你可以只写链接的简写形式,然后按TAB键扩充它(参见链接的缩写).如果你在输入前缀部分之后直接按<RET>,Org会根据前缀的不通为各种不通类型的链接提供不通的补全模式[fn:40].例如,如果你输入`file <RET>`,就会进入文件路径补全状态(另一种进入该状态的方式是用C-u C-c C-l,见下文),而如果你输入`bbdb <RET>`,就会进入联系人名称补全的状态
    C-u C-c C-l

插入一个指向本地文件的链接,你可以使用文件路径的补全功能来补全文件路径. 若插入的文件路径为相对路径,则该相对路径是相对与正在编辑的Org文件的目录来说的.你可以用`~/`代替你的home目录. 你也可用通过两个C-u前缀来强迫插入的链接为绝对路径

C-c C-l
光标需要停在链接上

当光标停在链接上时,C-c C-l允许你编辑链接的连接和描述信息

C-c C-o (org-open-at-point)

打开光标所在的链接,Org会使用web浏览器(由值browse-url-at-point定义)打开URL, 会使用VM/MH-E/Wanderlust/Gnus/BBDB打开相应的链接, 若链接为shell链接还会在在shell中执行链接中的命令. 若链接为内部链接,该命令会进行相应的搜索操作. 若光标出于标题的TAG列表处,则会创建相应的TAGS视图. 如果光标处于时间戳上,它会为该日期生成一个agenda. 另外如果光标处于’file:’类型的链接处,它会打开链接所指向的文件,如果指向的文件是远程文件或文本文件则直接用Emacs打开,如果是本地的非文本文件,则命令会挑选合适的程序打开. 命令是根据文件的扩展名来识别文件类型的. 哪种文件用哪种程序打开由org-file-apps选项配置. 如果你想用Emacs代替默认的程序来打开链接指向的文件,使用C-u前缀执行该命令. 而如果你不想用Emacs打开链接所指向的文件,使用C-u C-u前缀来调用该命令. 如果光标位于headline处,而这个headline刚好又不是个链接,则命令会搜索该headline下的所有链接并显示给你选择打开哪个链接. 如果你想setup the frame configuration for following links ,配置org-link-frame-setup变量

<RET>
若设置了’org-return-follows-link’值,<RET>也会打开光标所在的链接
鼠标右键 鼠标左键

在链接上单击鼠标右键,则会像执行了C-c C-o一样的打开链接. 在Emacs22或更高版本上,鼠标左键也能打开链接

鼠标中间键
类似于鼠标右键,但是强制使用Emacs打开链接,如果链接是内部链接,那么会在另一个窗口显示链接内容[fn:41]
C-c C-x C-v (org-toggle-inline-images)

切换是否内联显示连接的图片. 正常情况下,它只会内联哪些在链接中没有描述信息的图片,比如那些在导出时会内联的图片. 如果执行该命令时加了一个前缀参数,则命令也会显示那些有描述信息的链接图片. 通过配置变量`org-startup-with-inline-images`[fn:42]你也可以让emacs在一打开org的时候就内联显示图片.

C-c % (org-mark-ring-push)

把当前位置压入mark ring中,以方便以后方便跳回该位置. 那些打开链接的命令都会自动执行这一步

C-c & (org-mark-ring-goto)

跳回一个已经记录了的位置. 在访问内部链接和执行`C-c %`命令时都会记录下位置信息. 连续使用该命令多次可用跳到mark ring中更远的记录位置处

C-c C-x C-n (org-next-link) / C-c C-x C-p (org-previous-link)

跳到该buffer下一个/前一个链接处. 当到达buffer的最后一个/第一个链接处时,在执行该命令,第一次会显示失败,之后就跳到最后一个/第一个链接处继续搜索. 这两个命令的绑定键确实太长了;你可能希望用C-n和C-p来绑定:

(add-hook 'org-load-hook
  (lambda ()
    (define-key org-mode-map "\C-n" 'org-next-link)
    (define-key org-mode-map "\C-p" 'org-previous-link)))

在Org外使用链接 :从我的C源码中链接过来的?

不仅在Org模式中,在其他模式下你也可以插入和进入使用Org语法标示的链接. 要做到这一点,你可以就像下面所示创建两个全局命令(你可以选择自己喜欢的全局键)

(global-set-key "\C-c L" 'org-insert-link-global)
(global-set-key "\C-c o" 'org-open-at-point-global)

链接的缩写 :复杂链接的缩写形式 <<Link abbreviations>>

长URL输起来很麻烦,而且很多时候在文档中需要插入很多类似的链接. 这个时候你就可以使用链接缩写的功能了. 一个缩写的链接看起类似于

,[[linkword:tag][description]] 

这里tag是可选的. linkword必须是一个word,以字母开头后面跟着字母,数字,’-‘和’_’. Org根据变量’org-link-abbrev-alist’中的信息来分析缩写. 该变量把linkword与替代的文本关联起来.下面是个例子

(setq org-link-abbrev-alist
  '(("bugzilla" . "http://10.1.2.9/bugzilla/show_bug.cgi?id=")
    ("google"   . "http://www.google.com/search?q=")
    ("gmap"     . "http://maps.google.com/maps?q=%s")
    ("omap"     . "http://nominatim.openstreetmap.org/search?q=%s&polygon=1")
    ("ads"      . "http://adsabs.harvard.edu/cgi-bin/nph-abs_connect?author=%s&db_key=AST"))) 

如果被替代的文本中包含字符串’%s’, 字符串’%s’会被tag所取代. 否则tag会直接浮在字符串后面并以此来创建一个链接. 你也可以指定一个函数来创建链接,该函数要求只接受tag这唯一一个参数.

通过上面的设置,你可以使用’[[bugzilla:129] ](不含空格)’来连接到一个指定的bug, 使用’[[google:OrgMode] ]’来在web上搜索’OrgMode’,使用’[[gmap:51 Franklin Street,Boston] ]’显示自由软件组织在地图上的位置,使用’[[omap:Science Park 904, Amsterdam, The Netherlands] ]’来显示Carsten office在地图上的位置,使用’[[ads:Dominik,C] ]’来查找Org的作者在Emacs hacking时做了什么.

如果你只需要为单独一个Org buffer指定缩写,你可以在文件中定义:

#+LINK: bugzilla  http://10.1.2.9/bugzilla/show_bug.cgi?id=
#+LINK: google    http://www.google.com/search?q=%s 

在’[‘之后可以使用In-buffer补完功能来补完缩写. 你也可以定义一个名为’org-PREFIX-complete-link’的函数,该函数实现对使用C-c C-l插入的链接的特定支持动作(例如补完动作). 这个函数不接受任何参数并且返回带前置的完整链接.

文件链接中的搜索选项 :链接到特殊的位置

连接到文件的链接(文件链接)可以包含附加的信息来让Emacs在进入链接时跳转到文件的指定位置. 这个附加信息是放置在双[fn:43]冒号(::)之后,它可以是行号或者是搜索项. 例如当用C-c l创建一个连接到文件的链接时(参见章节处理链接), 这个链接会编码一个单词到当前行中,这个单词作为搜索字符串,当用C-c C-o进入链接时,就可以根据这个搜索字符串找回这一行.

下面是一些例子,演示了添加搜索项到文件链接的不同方式.

[[file:~/code/main.c::255]]
[[file:~/xx.org::My Target]]
[[file:~/xx.org::*My Target]]
[[file:~/xx.org::#my-custom-id]]
[[file:~/xx.org::/regexp/]] 
255
跳转到第255行
My Target
搜索链接项<<My Target>>,或者直接文本搜索’my target’, 类似于文件内链接的搜索,参见内部链接. 在导出HTML时(参见章节导出HTML),这种文件链接会导出为HTML链接,连接到被连接文件的指定anchor处.
*My Target
在Org文件中,精确搜索名为为My Target的标题
#my-custom-id
连接到CUSTOM_ID属性值为my-custom-id的标题
/regexp /

使用regexp做正则搜索. 该命令使用Emacs命令occur来在新窗口中列出所有的匹配项. 如果被连接文件处于Org模式下,org会使用org-occur命令来创建这些匹配的sparse tree

作为简化,一个文件名为空的文件连接,默认是连接到当前文件的. 例如’[[file:::find me] ]’(没有空格),会在当前文件中搜索’find me’,就好像’[[find me] ]’一样.

客户化搜索 :当内置的搜索不够用的时候

文件链接中的字符串搜索的默认实现并不能在所有情况下都能正常工作. 例如,BibTex数据库文件有很多类似于’year=”1993”’这样的条目,由于BibTex条目的唯一识别就是引用的键值(key),因此这些条目可能不能很好地进行字符串搜索(??意思可能是当对BibTex数据库进行搜索时,只希望在key中搜索,而不在value中搜索)

如果你遇到了这样的问题,你可以为特定的文件类型指定客户化的函数来实现正确的字符串搜索. 使用add-hook,这些函数需要添加到hook变量’org-create-file-search-functions’和变量’org-excute-file-search-functions’中. 要了解更多的信息可以参见这两个变量的docstring. org实际上使用这里定义的实现来对BibTex数据库文件进行搜索,你可以参见文件’org-bibtex.el’作为一个实现的例子.

TODO事项

Org-mode并不把TODO列表作为单独的一种文档来看待[fn:44]. 相反,由于在记录的时候常常会有TODO事项发生,因此TODO事项被认为是记录文件中中不可分割的一部分! 使用Org可用很容易的把各级条目标记为TODO事项. 通过这种方法,可用避免信息的重复,同时TODO事项的整个内容也是可见的

当然,这种方式组织的TODO事项就会分散在你的记录文件的各个地方. Org-mode通过提供各种函数(这些函数能够告诉你待办事项的这个概览情况)来补偿这一点.

最基本的TODO功能 :标记和显示TODO事项

任何以·TODO·卡头的标题都被认为是TODO事项,例如 #+BEGIN_SRC org

  *** TODO Write letter to Sam Fortune

#+END_SRC 关于TODO事项最重要的命令有:

C-c C-t (org-todo)

让当前事项的TODO状态在`无` `TODO`和`DONE`之间切换 在timeline和agenda缓存区中,使用t命令键也能够实现这样的切换(参见agenda缓存区中的命令)

C-u C-c C-t
使用补全方式或快速选择界面(需要设置)来选择特定的TODO关键字, 若要使用快速选择界面,你需要給每个TODO状态分配快捷键,更多信息,参见为各个文件分配TODO关键字设置tags
S-<right> / S-<left>

循环选择下一个/上一个TODO状态. 在事项有超过两个TODO状态的时候最有用(参见章节扩展TODO关键字). 要了解`shift-selection-mode`对改名了的而影响,参见章节与Org mode冲突的包.参见变量`org-treat-S-cursor-todo-selection-as-state-change`变量的说明

C-c / t (org-show-todo-key)

在一个sparse tree中查看TODO事项. 这回折叠起整个buffer只显示所有的未完成事项及其标题. 在命令前加上前缀(C-u C-c / t)可用搜索指定的TODO状态,你会被要求输入需要搜索的TODO状态(可用’KWD1|KWD2’的形式输入多个TODO状态),命令会列出匹配的所有事项. 如果调用该命令时附加了一个数字型的前缀参数N,则会匹配变量`org-to-keywords`中的第N个TODO状态. 如果调用该命令时加了两个前缀参数,则所有未完成和已完成的事项都会被找出来

C-c a t (org-todo-list)

显示全局的TODO列列表,从所有加入agenda的文件(参见Agenda视图)中收集所有的未完成事项到一个缓冲区中. 这个新buffer会处于agenda-mode,agenda-mode提供了很多命令来查看,操作buffer中的这些TODO事项(参见章节agenda buffer中的命令). 更多信息请见章节全局代办列表

S-M-<RET> (org-insert-todo-heading)

在当前TODO事项下面增加一个新的TODO事项 改变TODO状态也会触发tag改变事件. 细节方面请参见选型’org-todo-state-tags-triggers’的docstring

扩充TODO关键字 :工作流和委派

默认情况下,TODO事项只有两种状态:TODO和DONE. Org-mode允许你通过设置`TODO 关键字`来对自己的TODO事项进行划分.(保存在`org-todo-keywords`中). 不同的文件可用有自己独特的TODO关键字设置.

需要注意的是可用通过打tag的方式来对标题和TODO事项进行区分(参见章节Tag)

标示工作流状态的TODO关键字 :一步步的从TODO状态演化到DONE状态

你可以使用TODO关键字来标示事项处于工作流程中的不同状态.例如[fn:45]

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

这个`|`竖线划分了哪些状态是属于未完结状态,哪些状态是出于已完结状态. 如果你没有提供分隔线,那么最后那个状态被认为是已完结状态. 通过上面这个配置之后,当用命令`C-c C-t`切换状态时,会先从TODO切换到FEEDBACK,然后是FEEDBACK,最后是DONE和DELEGATED状态. 你也可以使用数字前缀来快速选择特定的状态,例如`C-3 C-c C–t`会使得状态立即编程VERIFY. 你也可以使用`S-<left>`来在这个序列中回退状态. 如果你定义了太多的状态,你可以使用in-buffer补全(参见补全章节)甚至是单个特定的选择键(参见章节快速设定TODO状态)来插入特定的TODO状态. 你也可用设定当改变TODO状态时记录下当时的时间戳数据,更多信息请参见跟踪TODO状态的改变

标示类型的TODO关键字 :这件事情我来做,其他的由Fred负责

你还可以使用TODO关键字标示事项的不同类型. 例如,你可能向标示有些事情是工作事项,有些事情是生活事项. 或者当你与其他人共同合作一个项目时,你可能想分派任务給某个人,这时你可以直接把那些人的名字当作TODO关键字来使用. 配置可能如下所示

,(setq org-todo-keywords '((type "Fred" "Sara" "Lucy" "|" "DONE")))

这时,这些关键字并不是用来标示工作流程中的不同状态的,它们被用来标示不同的类型. 所以这个时候的工作流程是:先把任务分配給某个人,然后等这件事完成了之后,再标记它为DONE状态. 它也支持使用命令`C-c C-t`[fn:46]来切换状态. 若你连续按几次`C-c C-t`的话(经过了一个循环之后),`C-c C-t`会变回去,再不同人物之间切换循环. 而当你中断了连续的`C-c C-t`做了其他操作之后之后,再按`C-c C-t`,该命令又变回从人物直接跳到DONE状态了. 同样的,你也可以用前缀参数或补完功能来快速选择特定的人物. 你还可以通过在sparse tree中查看某个特定人物的所有代办事项,方法是在`C-c / t`前加前缀的数字参数. 例如,如果你想看分配給Lucy的所有事项,你可以用命令`C- C-c / t`来查看. 同样的道理,若你想在一个单独的buffer中查看Lucy在agenda中各org文件记录的代办事项,你可以用命令`C- C-c a t`

在一个文件中设置多个关键字 :混用所有关键字

有时候,你可能想使用平行的多个TODO关键字集合. 举个例子来说,你可能向保留有基本的`TODO/DONE`,但是同时需要为bug修复定义一套工作流程状态,并且你还需要一个独立的状态表示事项已经被取消了(这是事项的状态不能是DONE,但是它也没有下一步的行动了). 这时你的配置可能如下

(setq org-todo-keywords
      '((sequence "TODO" "|" "DONE")
        (sequence "REPORT" "BUG" "KNOWNCAUSE" "|" "FIXED")
        (sequence "|" "CANCELED")))

各个平行的关键字集合之间的关键字不能出现重复,因为Org-mode需要根据该关键字决定该事项是属于哪种流程状态的. 这样子配置之后,`C-c C-t`只会在各个子序列内部循环切换状态,在这个例子中,`DONE`会先切换到`无`再切换到`TODO`,`FIXED`会切换到`无`再切换到`REPORT`. 因此你需要一种方法来让你在最初选择错误的时候可以切换到其他平行的子序列中. 除了直接敲入关键字或者使用补全功能选择关键字之外,你还可以通过以下命令实现这个目的:

C-u C-u C-c C-t / C-S-<right> / C-S-<left>
这些按键会从一个TODO子序列跳到下一个TODO子序列中,在上一个例子中,`C-u C-u C-c C-t`和`C-S-<right>`会从`TODO`或`DONE`直接跳到`REPORT`状态,然后跳到`CANCELED`状态. 需要注意,这里`C-S-<key>`的键绑定是和`shift-selection-mode与Org-mode冲突的包`冲突的
S-<right> / S-<left>
这俩命令会遍历所有子序列中的所有关键字,因此S-<right>会从`TODO`到`DONE`再到`REPORT`. 同样的,它也可能与`shift-selection-mode`有冲突,更多细节参见与Org-mode冲突的包

快速选择TODO状态 :通过单个字母快速选择TODO状态

如果你想快速改变事项的状态为某个状态,而不是在各个状态之间遍历,你可以为每个状态指定一个单字母的快捷键. 方法是在每个状态后面加上用括号括住的快捷键.像这样:

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

你键入`C-c C-t`然后输入状态的快捷键就会立即切换到指定的状态了. 如果你想去掉事项上的状态标识,则用`空格`代替快捷键[fn:47]

为各个文件设置独立的关键字 :不同的文件有不同的需求

很多时候我们需要为不同的文件设置不同的TODO关键字. 通过增加一些特殊的行,你可以为每个文件设置自己独有的TODO关键字. 例如,你可以在文件的任何一行定格写

#+TODO: TODO FEEDBACK VERIFY | DONE CANCELED
#+TYP_TODO: Fred Sara Lucy Mike | DONE

(你也可以使用`#+SEQ_TODO`,它的意思跟`#+TODO`一样,但是表达更清晰) 若需要定义多个平行的子序列,则这样配置:

#+TODO: TODO | DONE
#+TODO: REPORT BUG KNOWNCAUSE | FIXED
#+TODO: | CANCELED

你可以用补全的方式保证输入的关键字无误,方法是输入`#+`然后按下`M-<TAB>`

请注意,`|`后面的状态关键字(如果没有`|`则最后一个关键字)必须是代表完结状态的关键字(不一定需要DONE). 在输入完这些以`#+`开头的配置信息后,在配置信息行按下`C-c C-c`使该行的配置信息生效[fn:48]

TODO关键字的显示方式 :高亮状态

Org-mode为不同的状态关键字分配了不同的显示方式(emacs中大概是以face这个概念来表示显示方式). 默认情况下对于那些表示还未完结状态的状态关键字使用`org-todo`这个face,对于那些表示已完结状态的状态关键字使用`org-done`这个face. 如果你用到了2个以上的不同类别的状态,你可以通过配置变量`org-todo-keyword-faces`来为不同的状态关键字分配不同的face. 举个例子

(setq org-todo-keyword-faces
      '(("TODO" . org-warning) ("STARTED" . "yellow")
        ("CANCELED" . (:foreground "blue" :weight bold))))

像上面例子中`CANCELED`关键字这样直接定义face属性列表的方式,有可能不能正确的显示出来. 所以最好还是定义一个face然后使用它. 像`STARTED`这样,后面输入的是一个字符串的话,该字符串被解释成是颜色. 而变量`orgfaceseasyproperties`定义了改颜色是前景色还是背景色.

TODO事项之间的依赖关系 :当一个任务需要等待其他任务的时候

Org文件是由层级关系和列表组成的,这样的结构使得定义代办事项之间的依赖关系变得很容易. 通常在所有子任务完成之前是不能把父任务标记为完成状态的. 同时平级任务之间也可能存在一定的逻辑关系,使得后面的任务需要等待前面的任务都完成之后才能完成. 通过定义变量`org-enforce-todo-dependencies`,Org会阻止父任务在其子任务全部都完结的情况下被标记为完结状态. 此外,如果某个事项定义了`ORDERED`属性,那么它的子任务只有在前面子任务都完成之后才能被标识为已完成状态.下面是一个例子

* TODO Blocked until (two) is done
** DONE one
** TODO two

* Parent
,  :PROPERTIES:
,  :ORDERED: t
,  :END:
** TODO a
** TODO b, needs to wait for (a)
** TODO c, needs to wait for (a) and (b)
C-c C-x o (orgtoggleorderedproperty)
打开/关闭当前事项的`ORDERED`属性. 之所以要用给事项定义属性的方式来声明这种顺次的逻辑关系是因为这种逻辑关系往往只是对某项任务是这样的,它不像tag一样具有继承的特性. 当然如果你觉得属性常常被折叠起来不容易看到的话,也可以使用tag来跟踪该属性的变化,方法是定义变量`org-track-ordered-property-with-tag`.
C-u C-u C-u C-c C-t

绕开状态的那些限制,强制更改TODO状态 如果你设置了变量`org-agenda-dim-blocked-tasks`, 那么那些由于依赖关系未满足而无法关闭的代办事项在agenda视图中以灰色字体显示甚至是不显示(参见章节Agenda视图).

你也可以使得这种依赖关系对于checkbox也有效(参见章节checkbox).你可以设置变量`org-enforce-todo-checkbox-dependencies`. 然后如果某事项有未勾选掉的checkbox的话,也无法切换成完结状态

如果你需要更复杂的依赖关系(例如在不同的树n型结果或文件之间的依赖关系),请使用`org-depend.el`模块

记录处理过程 :记录处理过程的时间点和附加信息

Org-mode可以在你把代办事项从未完结状态切换到完结状态的时候记录下时间戳和其他一些信息,你甚至可以让它在每次切换状态的时候就记录下这些信息. 这套系统具有很高的可配置性,你可以对某个关键字,或某个文件甚至某个子树范围进行这样的配置. 要了解如何为事项统计所花的工作时间,可以参见章节统计工作时间

结束任务 :你是什么时候结束这项任务的

能够跟踪某任务什么时候完成是最基本的记录功能. 这项功能可以通过下面这条语句开启[fn:49]

(setq org-log-done 'time)

之后,每次你把一项未完结状态的任务切换到已完结状态的时候,都会在该任务标题下插入一行`CLOSED:[时间戳]`. 如果你把该任务状态又切换回未完结状态,这一行会被删除掉. 如果你希望除了记录时间戳还可以记录一些附加信息,配置[fn:50]

(setq org-log-done 'note)

这样当你把未完结状态的任务切换到已完结状态时,会被提示输入要保存的附加信息,该附加信息会存储在该任务下面,并以`Closing Note`开头

在timeline(参见章节单个文件的Timeline)和agenda(参见章节周/日agenda)视图中,你可以使用`l`键来显示每日带有’CLOSED’时间戳的代办事项,它会给你一个已完成事项的总括

跟踪任务状态 :什么时候任务状态发生了改变

有时候你可能想跟踪任务什么时候状态发生了改变,可能还想在状态发生改变的时候记录一些附加信息. 这些信息在插入时会插入到该事项标题的后面作为最新的信息列在第一排[fn:51]. 如果记录的附加信息太长了的话,你可能会希望把这些附加信息放入一个’抽屉’(drawer)中. 要实现这一点,需要配置变量`org-log-into-drawer`–推荐使用名为`LOGBOOK`的drawer. 若你想为某个子树设置其他的drawer方式,你可以为这个子树定义`LOG_INTO_DRAWER`属性.

Org-mode可以为每个TODO关键字定义记录时间戳和附加信息的行为. 你可以在关键字后面用括号括住`!`(表示记录时间戳)或者`@`(表示记录时间戳和附加信息).下面是一个配置的例子

(setq org-todo-keywords
  '((sequence "TODO(t)" "WAIT(w@/!)" "|" "DONE(d!)" "CANCELED(c@)")))

如果你想对配置了`@`的关键字只记录时间戳,不记录附加信息的话,只需要在提示输入附加信息的时候直接按下`C-c C-c`就行,这会提交一个空白的附加信息

在上面的例子中,你不仅定义了全局的TODO关键字,定义了它们的快捷键,而且你还指定了当事项设置为`DONE`状态的时候,记录下当时的时间戳[fn:52]. 当事项状态改为`WAIT`或`CANCELED`的时候,会提示记录下附加信息. 注意到`WAIT`状态有一个`/!`标志,这表示当离开WAIT状态进入到一个不记录任何信息的状态的时候,记录下当时的时间戳. 也就是说,当从`WAIT`切换到`DONE`状态的时候,并不触发记录时间戳的动作,因为DONE已经被配置为记录时间戳了. 而当从WAIT切换到TODO状态的时候,WAIT状态的`/!`设置会触发记录一个时间戳的动作,因为TODO并没有配置任何记录动作

你也可以把上面的设置限定到一个buffer中,方法是在buffer某行定格写

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

如果只想为某个子树或者某一个事项定义记录动作,你需要为改子树或者事项定义`LOGGING`属性. 如果你定义了非空的`LOGGING`属性,那么原先的记录动作的设置会被清空. 在配置`LOGGING`属性的时候,你可以使用`STARTUP`关键字(例如`lognotedone`或`logrepeat`).也可以明确指定为每个状态指定不同的记录设置(例如`TODO(!)`). 下面是一个例子

* TODO Log each state with only a time
,  :PROPERTIES:
,  :LOGGING: TODO(!) WAIT(!) DONE(!) CANCELED(!)
,  :END:
* TODO Only log when switching to WAIT, and when repeating
,  :PROPERTIES:
,  :LOGGING: WAIT(@) logrepeat
,  :END:
* TODO No logging at all
,  :PROPERTIES:
,  :LOGGING: nil
,  :END:

跟踪你的习惯 :你能坚持习惯多久

Org可以用来追踪习惯的一致性,这里所谓的”习惯”指的是拥有下列特征的待办事项.

  1. 通过配置变量`org-modules`,启用了`habits`模块
  2. 是一个未完成的任务,有一个未完成的状态标示该任务有下一步的行动
  3. `STYLE`属性值设置成了`habit`
  4. 该事项带有规划日期,而且规划日期中可以有`.+时间间隔`用来表示两次重复之间的间隔. `++时间间隔`表示该习惯有时间上的约束(比如,必须在周末完成),`+时间间隔`则表示改习惯不是一个经常性的事项,它可以在之前积压未办之事,然后在未来补完它(比如补写周报)
  5. 改习惯也可以使用类似`.+2d/3d`这样的符号标示最小/最大的间隔时间. `.+2d/3d`的意思是,你希望至少每三条做一次这个工作,但是最多每两天做一次这个工作
  6. 你最好为完结状态设置记录行为,这样会保留一些历史数据,这些历史数据可以以连线图的方式展现出来. 你不是必须要这样做,但是由此产生的连线图的意义就不大了.

为了给你一个直观的感受,下面展示一个带有历史数据的习惯的例子

** TODO Shave
,   SCHEDULED: <2009-10-17 Sat .+2d/4d>
,   - State "DONE"       from "TODO"       [2009-10-15 Thu]
,   - State "DONE"       from "TODO"       [2009-10-12 Mon]
,   - State "DONE"       from "TODO"       [2009-10-10 Sat]
,   - State "DONE"       from "TODO"       [2009-10-04 Sun]
,   - State "DONE"       from "TODO"       [2009-10-02 Fri]
,   - State "DONE"       from "TODO"       [2009-09-29 Tue]
,   - State "DONE"       from "TODO"       [2009-09-25 Fri]
,   - State "DONE"       from "TODO"       [2009-09-19 Sat]
,   - State "DONE"       from "TODO"       [2009-09-16 Wed]
,   - State "DONE"       from "TODO"       [2009-09-12 Sat]
,   :PROPERTIES:
,   :STYLE:    habit
,   :LAST_REPEAT: [2009-10-19 Mon 00:36]
,   :END:

这个例子的意思是:我希望最多每两天,最少每4天做一次这个事情(通过`SCHEDULED`日期和重复的时间间隔给定了). 假设今天是15号,那么在agenda中,该习惯会在17号(也就是2天之后)的地方显示生效. 在19号(也就是4天之后)的地方实效

把习惯用折线图展示出来可以显示在过去你坚持这项习惯的情况如何. 这个折线图显示了过去三个星期每天该习惯的完成情况,每天都根据完成情况用不同的颜色显示出来. 这些颜色有:

蓝色
表示当天任务没有完成
绿色
表示当天任务已经完成
黄色
表示任务在第二天就会过期了
红色
表示工作在当天已经延误了

另外除了用颜色标注每天的任务完成情况之外,弱于哪些任务在当天已经完成的任务会用星号标注出来. 会用感叹号标注当前日期出来.

org提供很多变量来改变agenda显示habit的方式

org-habit-graph-column
设定统计图从那一列开始画. 由于统计图会覆盖该列上的所有文本,因此最好保持你的habit标题简洁明了.
org-habit-preceding-days
指定从几天前开始统计数据
org-habit-following-days
指示统计到几天之后的数据
org-habit-show-habits-only-for-today
如果为非nil值的话,表示只在当天的agenda视图中显示habits. 默认情况下是设置为true的

最后,在agenda视图中按下`k`键会暂时让habit隐藏掉. 按’K’之后又会让habit显示出来. 它们也受到tag过滤的影响,例如你可以设定habit只能在某种特定的情况下才能被标记为完成.

优先级 :有些事情更重要一些

如果你经常使用Org-mode来进行任务安排的话,就应该会发现对各项任务分配优先级是很有必要的,方法是在TODO事项的标题前放上优先级标识(` priority cookie `),像这样:

*** TODO [#A] Write letter to Sam Fortune

默认情况下,Org-mode支持从高到低三个优先级,分别表示为`A`,`B`,`C`. 如果某个任务没有分配优先级,则被认为是`B`优先级. 为任务分配优先级的意义仅仅在于在agenda视图(参见周/日agenda)中可以依照优先级对任务进行排序. 通过定义变量`org-priority-faces`,你可以为不同的优先级分配不同的显示方式(face)

优先级标识可以放在任何大纲节点前,而不一定要放在TODO事项前

C-c ,
设置当前任务的优先级(`org-priority`). 执行该命令后,会提示你输入代表优先级的`A` `B` `C`. 如果你输入的是<SPC>则标识去除任务中的优先级标识. 若你在timeline或agenda视图中时,则可以使用`,`命令来改变优先级.(参见章节agenda视图中的命令).
S-<up> (org-priority-up) / S-<down> (org-priority-down)

提升/降低当前任务的优先级[fn:53]. 需要注意的时,这些键也同样可以用来改变时间戳(参见章节创造时间戳). 同样这些按键也可能与`shift-selection-mode`相互冲突,具体情况参见与Org-mode冲突的包

通过设置变量`org-highest-priority`,`org-lowest-priority`和`org-default-priority`的值,你可以自定义优先级的区间. 若想对某个文件设置优先级区间,你可以像下面那样设置(准照最高优先级,最低优先级,默认优先级的顺序来设置,同时请确保最高优先级在字母表上要比最低优先级靠前)

#+PRIORITIES: A C B

划分子任务 :划分任务为可管理的碎片

将一件很复杂的任务分解为简单一些,更易管理的子任务是很有必要的. 你可以在任务事项下面创建新的子树大纲(子任务作为子树的各节点)的方式来表达这种分层关系[fn:54]. 若你想在父任务上显示子任务完成的情况,可以在父任务标题的任何地方插入`[/ ]`或`[% ]`. 每当有子任务被标识为已完结状态之后,这两个标识会被更新为子任务的完成进度,在这两个标识上按下`C-c C-c`也能够强制更新这两个标识的信息.下面是一个例子:

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

如果一个任务标题下面既有check列表,也有代办的TODO子任务,那么org就不清楚应该怎么统计子任务的完成情况了. 这时需要设置属性`COOKIE_DATA`的值为`checkbox`或者`todo`来明确指示统计时以哪个为准

如果你想在统计子任务完成情况的时候,不是仅仅统计直接下属的子任务的情况,而是统计所有层级的下属子任务,那么你需要配置变量`org-hierarchical-todo-statistics`. 如果你只是对某个特定的父任务有这种需求,那么为该父任务设置`COOKIE_DATA`属性,并且确保该属性的值包含有`recursive`. 下面是一个例子

* Parent capturing statistics [2/20]
,  :PROPERTIES:
,  :COOKIE_DATA: todo recursive
,  :END:

如果你希望父任务在所有子任务都标记为完结状态后,自动也切换到完结状态,你可以用下面所示的配置:

(defun org-summary-todo (n-done n-not-done)
  "Switch entry to DONE when all subentries are done, to TODO otherwise."
  (let (org-log-done org-log-states)   ; turn off logging
    (org-todo (if (= n-not-done 0) "DONE" "TODO"))))

(add-hook 'org-after-todo-statistics-hook 'org-summary-todo)

当然,你也可以使用check列表代替子任务的作用

checkbox :标记列表

如果一个事项是不是以标题的形式而是以纯文本列表[fn:55](参见纯文本列表)的形式展现的,同时它又是以`[ ]`开头的,那么它就被当成是一个代检查事项(checkbox)看待. checkbox跟待办事项(参见待办事项)很类似,但是相比起来更加的轻量化. checkbox不回显示在全局的未完成事项列表(TODO列表)中,因此它常常用来表示将一个任务分隔成几个简单的步骤,或者用来作为待购清单来使用. 要切换checkbox的状态(完成/未完成状态),需要按下`C-c C-c`,或者使用鼠标点击(多亏了Piotr Zielinski的`org-mouse.el`)

下面是一个checkbox列表的例子

* TODO Organize party [2/4]
,  - [-] call people [1/3]
,    - [ ] Peter
,    - [X] Sarah
,    - [ ] Sam
,  - [X] order food
,  - [ ] think about what music to play
,  - [X] talk to the neighbors

checkbox具有继承的特性,因此如果一个checkbox具有子checkbox的话,对子checkbox的完成状态进行切换的时候,父checkbox也会自动根据是没有/部分/全部子checkbox完成状况来做出相应的改变

在上面例子中,第一行和第二行的`[2/4 ]`和`[1/3 ]`展示了一共有多少个checkbox,其中多少个checkbox一件完成了. 这使得你不用展开就能知道还剩下多少个checkbox没有完成. 这种统计信息的展示可以放在标题或者文本列表的任何地方,而且它只会统计直接子任务的完成情况[fn:56]. 为了得到这种统计信息的展示,你需要自己输入`[/ ]`或`[% ]`. 如果你使用的是`[/ ]`,那么你会得到`[n/m]`这样的展示方法(n表示已完成数,m表示未完成数). 如果你输入的是`[% ]`,那么你会得到一个百分比的展示. 若在标题的子树下,既有TODO事项,又有checkbox,那么展示的可能为TODO事项的统计结果(若触发改变的是由于子TODO事项的状态改变而引起的)也可能是checkbox的统计结果(若触发改变的结果是由于checkbox的状态改变引起的),这样就显得很混乱. 要解决这个问题,设置该标题的`COOKIE_DATA`属性值为`checkbox`或者`todo`即刻

如果在当前的大纲节点上加了`ORDERED`属性,这就告诉orgcheckbox必须从上到下一个一个的被完结, 否则会有报错.

关于checkbox的命令有以下这些:

C-c C-c (org-toggle-checkbox)

切换光标所在checkbox的完结状态. 如果加了一个前置参数(也就是用按键`C-u C-c c-c`)则增加/移除checkbox标志(使它在checkbox和普通列表之间切换)[fn:57], 如果加了两个前置参数(`C-u C-u C-c C-c`)则checkbox的标志设为`[-]`,这种标志的意思是其为一种中间状态

C-c C-x C-b (org-toggle-checkbox)

切换光标所在checkbox的完结状态. 如果加了两个前置参数(`C-u C-u C-c C-c`)则checkbox的标志设为`[-]`,这种标志的意思是其为一种中间状态

  • 如果存在一个选择域,则切换该选择区域的第一个checkbox的完结状态,同时选择区域的其他checkbox的完结状态都改为以第一个checkbox的完结状态为准. 如果调用该命令时带了一个前置参数(`C-u C-c C-x C-b`)则增加/删除该区域中所有事项的checkbox标志
  • 如果对一个标题进行该操作, 则切换该标题到下一标题间的所有checkbox的状态(不是整个子树)
  • 如果没有选择区域,则切换光标所在的checkbox的状态
    M-s-<RET> (org-insert-todo-heading)

插入一个新的checkbox,这只有当光标处于普通列表中时才有效(参见普通列表)

C-c C-x o (org-toggle-ordered-property)

切换是否具有`ORDERED`属性. 如果你希望能够以tag的形式来最终`ORDERED`属性的值,你可以设置变量`org-track-ordered-property-with-tag`

C-c # (org-update-statistics-cookies)

更新当前大纲项的统计信息, 若使用了`C-u`前缀,则更新整个文件的统计信息. 当你用`C-c C-c`切换一个checkbox的完结状态或者用`M-S-<RET>`新增加一个checkbox的时候,会自动更新checkbox的统计信息. 同样,当改变TODO事项的状态时,也会自动更新TODO事项的统计信息. 但是如果你删除checkbox和TODO事项,或者手工增加/修改checkbox和TODO事项,那你就需要手工调用这个命令,以强制同步更新统计数据

Tags

每个标题都可以包含多个tag; 这些tag应该放在标题的末尾位置. tag通常由字母,汉字,数字,-和@组成. tag的前后必须被冒号包括,像这样`:work:`. 可以同时指定多个tag,像这样`:work:urgent:`. tag默认是用跟标题一样的颜色,但是加粗显示. 你也可以为特定的tag定义特定的显示方式(face),方法是配置变量`org-tag-faces`, 这跟配置TODO关键字的face的方法差不多(参见TODO关键字的显示方式)

Tag的继承特性 :tag在大纲中具有继承的特性

tag具有继承的特性. 如果一个标题具有某个tag,那么它的所有子标题自动继承了这个tag,例如,

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

上例中,最后那一行的标题虽然看起来只有一个tag,但是其实它有4个tag:`:work:`,`:boss:`,`:notes:`和`:action:`. 你也可以设置文件级的tag,这样所有该文件的标题,自动继承了这些文件级的tag. 方法为在文件中加入这样一行[fn:58]

#+FILETAGS: :Peter:Boss:Secret:

如果你想只限定某几个tag具有继承性,或者根本就不想让tag具有继承性,那么你可以通过配置变量`org-use-tag-inheritance`和`org-tags-exclude-from-inheritance`来实现

如果tag的继承特性被打开,那么在作tag搜索的时候,若某个父标题匹配了这次搜索,那么它的子树也同样匹配这次搜索[fn:59],这样的话,匹配列表恐怕就会过长. 如果你只想让子树中第一个匹配项可见,请配置变量`org-tags-match-list-sublevels`(我们不推荐这么做)

设置Tag :如何为标题分配tag

你可以直接通过在标题后面输入tag的方式給标题打tag. 输入冒号之后,按下`M-<TAB>`,会提供对tag的补全. 你也可以用下面的命令来插入tag

C-c C-q (org-set-tags-command)

为当前标题输入新的tag. Org-mode同时也提供补全功能,或給key设定单字符的快捷键,具体内容见下文. 在按下<RET>之后,就会插入tag,并且tag自动与`org-tags-column`代表的列对齐. 当调用时带了`C-u`前缀参数时, 当前buffer中的所有tag都会与该列对齐,这样会显得很工整. 另外,当你对标题进行升级/降级,或者改变TODO状态的时候,也会自动对齐tag的位置,参见章节最基本的TODO功能

C-c C-c (org-set-tags-command)

当光标位于标题上时,这个功能与`C-c C-q`一样.

Org在插入tag时维护了一个tag列表. 默认情况下,这个tag列表动态的包含了当前buffer中的所有tag. 你也可以通过变量`org-tag-alist`来设置一个全局的固定的tag列表. 当然你也可以单独为一个文件设置默认的tag列表.

#+TAGS: @work @home @tennisclub
#+TAGS: laptop car pc sailboat

如果你通过变量`org-tag-alist`设置了一个全局的tag列表,但是在某些文件中,又希望能够动态获取tag列表,你只需要在文件中加入一个空白的TAG选项即刻

#+TAGS:

如果你有一些tag是每个文件都要用到的,你可以把这些tag放入变量`org-tag-persistent-alist`中,这样org文件除了具有TAGS选项所设定的tag外,还具有这个变量所定义的那些tag. 如果某个文件不想包含该变量所定义的tag,只需要在STARTUP选项行中添加:

#+STARTUP: noptag

默认情况下,Org-mode在输入tag时提供的是标准minibuffer补全方式. 然而其实它具有另一个更快捷的tag选择方法名叫`快速tag选择法(fast tag selection)`. 它可以让你只用一个按键就可以选择/取消一个tag. 为了让该方法能够很好的工作,你需要为你最常用的tag都分配唯一的单独键. 你可以通过在`.emacs`文件中配置变量`org-tag-alist`来实现. 例如你可能在许多文件中都会用到`:@home:`这个tag,你就可以这样定义

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

如果tag只是在当前文件中有效,你可以在文件中设置TAGS选项行像这样:

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

插入tag时会在一个新窗口中显示可用的tag供你选择. 若你想在某个tag之后换行显示,你只需要在它之后插入`\n`即刻:

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

或者你也可用写成两行

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

用大括号括起来的tag,相互之间只能选择一个标识,例如

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

上面的例子说明了,最多只能选择`@work`,`@home`和`@tennisclub`三个之中的一个,作为tag标识. 当然多个组之间的tag可用放在一起 当然,别忘了,在这些配置行上按下`C-c C-c`才回使这些改动生效.

若想在设置变量`org-tags-alist`时也表达这种组内相互排斥的tag,你需要用`:startgroup`和`:endgroup`来代替`{`和`}`. 同样的,你也可用用`:newline`来标识断行. 要把上面哪个例子中的tag设置变成全局性的,可用使用如下配置

,(setq org-tag-alist '((:startgroup . nil)
,                      ("@work" . ?w) ("@home" . ?h)
,                      ("@tennisclub" . ?t)
,                      (:endgroup . nil)
,                      ("laptop" . ?l) ("pc" . ?p)))

如果至少有一个tag分配了快捷键,那么在按下`C-c C-c`之后会显示给你一个特殊的界面,在这里列出了继承到的tag,当前标题行所明确指定的tag和所有其他可用tag,以及这些tag的对应快捷键[fn:60]. 在这个界面中,你可以使用如下快捷键:

a-z…
按下分配給tag的快捷键会添加/删除当前行的相应tag. 如果你选择的tag刚好跟其他tag处于同一个相互排斥的组,那么其他的tag会自动被移除.
<TAB>
会在minibuffer中提示你输入tag,这个tag可用是全新的. 你也可以同时添加多个tag:只需要用冒号将它们分开就行
<SPC>
清空当前行的所有tag
<RET>
保存当前的tag修改
C-g
放弃当前的修改
q
如果`q`没有被分配給tag当快捷键,那么它跟`C-g`一样
!
关闭相互排斥组的约束,用这个命令可用将相互排斥组的多个tag放在一起
C-c
开/闭自动退出模式,如果打开自动退出模式,则org只接收下一个tag的命令,然后就自动退出(见下文). 如果你处于expert mode下,那么这个`C-c`会显示tag选择窗口(也就是说,在expert模式下,C-c C-c默认也不显示tag选择窗口)

这些命令使得你可用用很少的按键就可以为标题分配tag. 举例来说,如果你使用了上面的配置,你可以用`C-c C-c <SPC> h l p <RET>`来清空当前行的tag,然后为当前行分配‘@home’,‘laptop’和‘pc’标签. 使用`C-c C-c w <RET>`或`C-c C-c C-c w`来将`@home`变成`@work`标签. 通过` C-c C-c <TAB> S a r a h <RET> <RET>`来为当前行分配新标签`sarah`

如果你发现你对tag的修改大多数时候只需要按一个键就可用完成,这时,你可以设置变量`org-fast-tag-selection-single-key`. 设置之后你不再需要按`<RET>`来退出快速tag选择窗口–它会在你做出第一次修改之后立即退出. 如果偶尔你需要作多处修改,你只需要按下`C-c`来取消自动退出模式即可(其实设置了`org-fast-tag-selection-single-key`之后,再按下`C-c C-c`,其效果跟`C-c C-c C-c`一样). 如果你设置该变量的值为`expert`,那么这个tag选择窗口甚至不会出现,除非你再按一次`C-c`才会出现

Tag group(Org8.x的特性)

在一系列相互排斥的tag列表中,第一个tag可以定义为group tag. 当你搜索group tag时,实际搜索的是该group中的所有tag. 在agenda视图中过滤出来group tag的结果是将带有group中任何一个tag的headline給过滤出来. 这个特性使得tag搜索和过滤更为便利.

你可以通过在group tag和其他tag之间插入`:`的方式来设置group tag. 这种方式下,各tag之间只能使用空格来进行分隔. 例如

#+TAGS: { @read : @read_book @read_ebook }

在上面的例子中,`@read`就是`@read`,`@read_book`和`@read_ebook`这三个tag集合的goup tag.

你也可以在设置变量`org-tag-alist`时使用`:grouptags`关键字:

(setq org-tag-alist '((:startgroup . nil)
                      ("@read" . nil)
                      (:grouptags . nil)
                      ("@read_book" . nil)
                      ("@read_ebook" . nil)
                      (:endgroup . nil)))

你不能嵌套group tag,也不能作为其他group中的普通tag

若你想临时禁用group tag特性,可以按`C-c C-x q`(org-toggle-tags-groups)来开关group tag支持. 如果你想完全禁用tag group功能,设置变量`org-group-tags`为nil

搜索Tag :搜索tag的组合

一旦完善的tag系统建立起来了,我们就可以利用它将相关联的信息搜集起来

C-c / m 或 C-c \ (org-match-sparse-tree)

将所有匹配tag搜索的标题搜集起来放到一个sparse tree中. 如果带了`C-u`前缀参,则会忽略哪些不是TODO事项的标题

C-c a m (org-tags-view)

从agenda文件中搜集所有匹配tag搜索的标题. 参见章节匹配tag和属性

C-c a M (org-tags-view)

从agenda文件中搜索所有匹配tag搜索的标题,但是只搜索TODO事项,并且强制进行子树的匹配(参见变量`org-tags-match-list-sublevels`)

所有这些命令都会提示你输入匹配字符串, 在输入时,允许你使用基本的布尔逻辑,比如`+boss_urgent-project1`的意思是找tag中带有`boss`和`urgent`但是没有`project1`的事项. 而`Kathy|Sally`的意思是照tag中包含`Kathy`或者`Sally`的事项. 还有其他许多的表达式可以用来匹配TODO关键字,事项的层次和属性的. 更多内容请参见匹配tag和属性

属性和column

属性其实就是一个键值对,它与org文件中的条目相关联. 属性可用设置为与Org文件中的某个特定条目,或者某棵树下的所有条目,或者整个buffer中的条目相关联.

在Org-mode中,属性有两种主要的功能. 第一个功能是类似于带值的tag. 想象一下你需要维护一个记录bug和发布版本的文档. 你可以使用类似`:release_1:`或`release_2`这样的tag来标注,或者你可以可用使用一个名叫`:Release:`的属性,但是在不同的子树中给它分配不同的值(比如`1.0`,`2.0`). 第二个功能是使用属性来实现数据库的基本功能. 例如你在记录你的CD,給它分配的属性可用是`专辑,演唱者,发布日期`等等

通过column视图(参见Column视图),可用很方便的编辑和查看属性

属性的语法规则 :如何声明属性

属性是以键值对的形式出现的. 当需要分配属性时,属性需要放入一个名为`PROPERTIES`的特殊抽屉(drawer)中. 每个属性一行,键(用冒号括起来)在前,值在后. 下面是一个例子

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

根据变量`org-use-property-inheritance`的值的不同,属性可能具有也可能不具有继承性,详见继承的继承性

你可能想设定属性`:Xyz:`只能有哪些值,你可以通过定义一个名为`:Xyz_ALL`的属性来做到这一点. `:Xyz_ALL:`是一类特殊的属性,该属性具有继承性,因此如果你在第一层条目上设置了这样的属性,它会对整个树生效. 通过约束属性的所有值,可以减少设置属性时输入错误的概率. 举个例子,要记录收集的CD,你可以预定义好出版人和碟片数量,向下面一样:

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

如果你向定义在全file中都有效的属性,在文件中加入这么一行:

#+PROPERTY: NDisks_ALL 1 2 3 4

如果你想对一个已经存在的属性,添加一个值,只需要在定义时在属性名称后面附上一个`+`号. 例如下面的例子中,属性`var`的值为`foo=1 bar=2`

#+PROPERTY: var  foo=1
#+PROPERTY: var+ bar=2

你不仅可以对定义的属性添加值,还能对继承过来的属性添加值. 下面的例子中,`Goldberg Variations`子树中的`genres`属性的值为`Classic Baroque`

* CD collection
** Classic
,    :PROPERTIES:
,    :GENRES: Classic
,    :END:
*** Goldberg Variations
,    :PROPERTIES:
,    :Title:     Goldberg Variations
,    :Composer:  J.S. Bach
,    :Artist:    Glen Gould
,    :Publisher: Deutsche Grammophon
,    :NDisks:    1
,    :GENRES+:   Baroque
,    :END:

需要注意的是,每个Drawer中的每个属性只能定义一行. 全局变量`org-global-peroperties`定义的属性被所有的Org文件中的所有条目所继承

下面有一些关于属性的命令

M-<TAB> (pcomplete)

再输入冒号之后按下这个命令键,会列出当前文件可用所有属性名,可用直接用鼠标点击要加入的属性名即可

C-c C-x p (org-set-property)

设置属性. 这个命令会提示你输入要编辑的属性名称和属性值. 如果输入的新的属性名,则会新增该属性

S-<right> (org-peroperty-next-allowed-value) 或 S-<left> (org-peroperty-previous-allowed-value)

将光标所在的属性切换到上一个/下一个可选值

C-c C-c (org-peroperty-action)

在属性抽屉中按下这个命令键,会显示出各种操作属性的命令,可进行设置属性,删除属性,全局删除属性,计算属性值等操作. 具体说明见下文

C-c C-c s (org-set-peroperty)

设置当前抽屉中的的任选某个属性. 属性名和属性值都可以以计算的方式插入

C-c C-c d (org-delete-peroperty)

删除当前抽屉中的某个属性

C-c C-c D (org-delete-property-globally)

全局删除某个属性,对当前文件中的所有条目都生效

C-c C-c c (org-compute-peroperty-at-point)

计算光标所在的属性,

特殊的属性 :Org-mode的其他特性说明

一些特定的属性被定义用来开启Org-mode的一些特性(比如前面章节中讲到的TODO状态和优先级). 之所以提供这些特殊的属性,是为了让你可以在column视图中查看到这些状态,还可以在搜索时匹配这些状态. 下面列出的这些特殊属性名,这些属性(除了`:CATEGORY:`)不应该放入属性抽屉中中

TODO         The TODO keyword of the entry.
TAGS         The tags defined directly in the headline.
ALLTAGS      All tags, including inherited ones.
CATEGORY     The category of an entry.
PRIORITY     The priority of the entry, a string with a single letter.
DEADLINE     The deadline time string, without the angular brackets.
SCHEDULED    The scheduling timestamp, without the angular brackets.
CLOSED       When was this entry closed?
TIMESTAMP    The first keyword-less timestamp in the entry.
TIMESTAMP_IA The first inactive timestamp in the entry.
CLOCKSUM     The sum of CLOCK intervals in the subtree.  org-clock-sum
             must be run first to compute the values in the current buffer.
BLOCKED      "t" if task is currently blocked by children or siblings
ITEM         The content of the entry.
FILE         The filename the entry is located in.

搜索属性 :匹配属性值

属性搜索的命令和tag搜索(参见章节tag搜索)的命令一样的

C-c / m 或 C-c \ (org-match-sparse-tree)

将所有匹配tag搜索的标题搜集起来放到一个sparse tree中. 如果带了`C-u`前缀参,则会忽略哪些不是TODO事项的标题

C-c a m (org-tags-view)

从agenda文件中搜集所有匹配tag/属性搜索的标题. 参见章节匹配tag和属性

C-c a M (org-tags-view)

从agenda文件中搜索所有匹配tag搜索的标题,但是只搜索TODO事项,并且强制进行子树的匹配(参见变量`org-tags-match-list-sublevels`) 关于搜索串的语法参见匹配tag和属性

还有一个搜索单个属性的命令:

  • C-c / p

该命令根据属性值进行搜索匹配. 它首先提示你输入要搜索的属性名,然后是要匹配的值. 然后就会查找出所有拥有该属性并且属性值为指定值的条目. 在输入待匹配的属性值时,用`{}`括起来的值被当作是正则表达式处理.

属性继承 :下级继承上级的属性值

属性可以具有继承性.但是默认情况下,Org-mode不打开该特性,因为它会极大地拖慢属性搜索的速度并且实用性也不大. 然而如果你觉得很有必要打开它的继承性,你可以通过设置`org-use-property-inheritance`来实现. `org-use-property-inheritance`的值为`t`表示开启继承性,为`nil`表示关闭继承性

Org-mode中也有一些属性是强制具有继承性的.

COLUMNS

`:COLUMNS:`属性定义了column视图的格式(参见章节Column视图). 它的继承性的意义为:定义了`:COLUMNS:`属性的层次被认为是column视图表格的开始部分.它与子树中column视图被开启的位置相互独立(independently of the location in the subtree from where columns view is turned on. )

CATEGORY
在agenda视图中显示时,通过`:CATEGORY:`属性设置的类别对整个子树都有效
ARCHIVE
在归档时有用,`:ARCHIVE:`属性定义了整个子树中的归档位置(参见章节移动树到归档文件中)
LOGGING
`:LOGGING:`属性为条目或子树定义了记录日志的设置情况(参见章节追踪TODO状态的改变)

Column视图 :以表格的方式浏览与编辑

要查看和编辑一个大纲树中的属性,有一个很好的方法,那就是column视图. 在column视图中,每个大纲节点都被转换为表格中的一行. 各条目的属性就是表格中的列. Org-mode并不实际修改buffer,而只是通过在标题上多现实出一个表格结构体的方式实现column视图的. 因此,即使标题被转换成了表格的行了,但是你依然可以切换大纲树的可视性. 例如,你通过切换到目录(CONTENTS)视图模式(通过`S-<TAB> S-<TAB>`切换,若在column视图中,则直接按`c`即可),得到一个紧凑的概况表格. 这时,你依然可以打开,阅读和编辑每个标题下面的各个条目. 你也可以在执行sparse树命令之后再切换到column视图,通过这种方式,你可以在表格中只现在筛选出来的内容. 你也可以在agengda视图中切换成Column显示方法,这样你可以在表格中同时显示多个文件中的筛选内容.

定义列 :COLUMNS格式属性

要想使用column视图,先得定义列. 这是通过定义列格式行(column format line)的方式来进行的

列定义的范围 :在哪里定义?作用的范围有哪些

要定义整个文件范围的列格式,使用类似下面的行

#+COLUMNS: %25ITEM %TAGS %PRIORITY %TODO

如果只想对某颗树的范围内定义列格式,对这棵树的最顶层节点添加`:COLUMNS:`属性,例如

** Top node for columns view
,   :PROPERTIES:
,   :COLUMNS: %25ITEM %TAGS %PRIORITY %TODO
,   :END:

`:COLUMNS:`属性具有继承性,因此你可以在上层为各子层定义足够普遍的格式定义,然后在编辑更深层次时定义更特化的格式定义

列属性 :列的内容和展示

column的定义式中可以包含有列的属性. 一般来说列的定义式看起来是这样做的

,%[width]property[(title)][{summary-type}]

除了百分号和属性名之外,所有的都是可选的. 各部分的意思如下所示

width           整型,代表了列的宽度,如果忽略则由org自动决定
                
property        该列所表示的属性,可以是上文提到的哪些特殊属性
                
title           列的标题,如果忽略,则会使用属性名代替
                
{summary-type}  总和的类型,如果指定了,那么父节点的列值由其下子节点的值计算得到
                支持的总和类型包括:
                {+}       Sum numbers in this column.
                {+;%.1f}  Like ‘+’, but format result with ‘%.1f’.
                {$}       Currency, short for ‘+;%.2f’.
                {:}       Sum times, HH:MM, plain numbers are hours.
                {X}       Checkbox status, ‘[X]’ if all children are ‘[X]’.
                {X/}      Checkbox status, ‘[n/m]’.
                {X%}      Checkbox status, ‘[n%]’.
                {min}     Smallest number in column.
                {max}     Largest number.
                {mean}    Arithmetic mean of numbers.
                {:min}    Smallest time value in column.
                {:max}    Largest time value.
                {:mean}   Arithmetic mean of time values.
                {@min}    Minimum age (in days/hours/mins/seconds).
                {@max}    Maximum age (in days/hours/mins/seconds).
                {@mean}   Arithmetic mean of ages (in days/hours/mins/seconds).
                {est+}    区间的总和

需要注意的是,一个属性只能有一种总和类型. 低层列当涉及到相同的属性时,会显示一样的总和信息.

`est+`这种总和类型需要多做一些说明. 它常常用来合计那些范围数据. 例如你在评估一项任务的时候可能不会说就是5天搞定,相反你可能会说大概5-6天的时候能搞定,甚至如果你对这个任务一无所知的化可能估计要1-10天才能搞定. 这两种区间平均来说都是5.5天搞定,但是第一种表达明显更精确一点.

当在计算这种区间的的总和时,一般的做法是把各区间的最低值和最高值相加形成一个区间,然而这个区间往往跨度太大而没什么用. `est+`则不采用这种计算方法. 它会计算各区间的平均值和方差,并根据总和生成一个最终估计. 举个例子, 假设你有10项任务,每项任务估计都要话0.5-2天才能昨晚. 如果采用一般的方法直接累计的结果是完成这10项任务需要花5-20天的时间. 然而如果使用`est+`这种计算方式则估计出值为10-15天,这个值明显更真实一些.

下面是一个完整的列定义的例子.[fn:61]

,:COLUMNS:  %25ITEM %9Approved(Approved?){X} %Owner %11Status %10Time_Estimate{:} %CLOCKSUM
,:Owner_ALL:    Tammy Mark Karl Lisa Don
,:Status_ALL:   "In progress" "Not started yet" "Finished" ""
,:Approved_ALL: "[ ]" "[X]"

第一列`%25ITEM`的意思是取条目(例如标题)的前25个字节为内容. 基本上你在定义列定义时都应该以`ITEM列`开头. 其他的列定义部分则定义了一个名为`Owner`的列,该列限定了几个可选值. 定义了一个名为`Status`的列并定义了4个可选值, 还有放置checkbox的列`Approved`. 若`%`之后没有定义列宽,则列宽会刚好足够显示所有的值. `Approved`列有一个被修改过的标题(`Approved?`,这里有个问号). 对于列`Time_Estimate`会自动累计时间段,格式为`HH:MM`, 而对于列`Approved`来说,如果所有的子节点都check过了,则会显示一个`[X]`表示完结状态. `CLOCKSUM`列比较特殊,它列出子树中的CLOCK间隔时间的总和

使用column视图 :如何创建和使用column视图

  • 开/关column视图
    C-c C-x C-c (org-columns)

    打开column视图模式. 如果执行命令时光标在文件第一个标题上面,那么整个文件都会开启column视图模式,column视图现实时是参照`#+COLUMNS`的定义来现实的. 如果光标是在大纲内部的化,命令会从改点开始往下搜索所有子树,查找`:COLUMNS:`属性. 当找到一个`:COLUMNS:`属性后,会为以带有该属性的条目为起点的子树建立column视图表格. 如果没有找到`:COLUMNS:`属性,那么会以光标所在条目为起点的子树建立column视图,其参照的格式为`#+COLUMNS`行或变量`org-columns-default-format`中的定义

    r (org-columns-redo)
    刷新column视图,让它反应最近的修改
    g (org-columns-redo)
    跟`r`一样
    q (org-columns-quit)
    退出column视图
  • 编辑值
    <left> <right> <up> <down>

    在column视图中的域之间跳转

    S-<left> /S-<right>
    切换域中的值为下一个/上一个可能的值,因此你必须要为该属性定义好可选的值
    1…9,0
    直接选择第N个可选值,0表示选择第10个可选值
    n (org-columns-next-allowed-value) /p (org-columns-previous-allowed-value)
    跟S-<left> /S-<right>一样
    e (org-columns-edit-value)
    编辑光标所在的属性值.
    C-c C-c (org-columns-set-tags-or-toggle)
    当光标处于checkbox处时,切换它的勾选状态
    v (org-columns-show-value)
    查看属性的完整值,这在当列宽度比值宽度要小的时候很有用
    a (org-columns-edit-allowed)
    编辑该属性的可选值. 如果之前就已经设定了可选值,那么修改过的值就存储在之前设定可选值的位置.否则的话新的可选值会记录在当前column视图的第一个条目处.
  • 修改表column视图格结构
    < (org-columns-narrow) / > (org-columns-widen)

    缩小/放大列的宽度

    S-M-<right> (org-columns-new)

    在当前列的左边插入一行新列

    S-M-<left> (org-columns-delete)
    删除当前列

捕捉column视图 :column视图的动态区块

由于column视图并不正真修改buffer,它只是一种显示方式而已,因此它不能直接被导出或者被打印出来. 如果你需要捕获column视图的内容,你需要定义`columnview`动态区块(dynamic block). 这种动态区块的框架类似于这样的:

* The column view
#+BEGIN: columnview :hlines 1 :id "label"

#+END:

定义动态区块时可以使用以下这些参数:

:id
这是最重要的参数. 因为动态区块所处的位置跟要捕获的column视图的位置很可能不一致,这就要求用一种方法来定义那部分的column视图需要被捕获. 这个参数有4个值
local     use the tree in which the capture block is located
global    make a global view, including all headings in the file
"file:path-to-file"
          run column view at the top of this file
"ID"      call column view in the tree that has an :ID:
          property with the value label.  You can use
          M-x org-id-copy to create a globally unique ID for
          the current entry and copy it to the kill-ring.
    
:hlines
如果为`t`,则表示每一行后面都插入一条横线. 若设置为数字N,则表示对于所有层级<=N的标题,在标题前插入一条横线
vlines
若设置为`t`,则表示强制用竖线分隔各属性列
:maxlevel
若设置为数字N,表示不捕捉层级在N级以下的条目
:skip-empty-rows
若设置为`t`,则会跳过那些除了`ITEM`属性列外,其他属性列都是空值的行

下面还有一些命令是用来插入或更新动态区块(dynamic block)的

C-c C-x i (org-insert-columns-dblock)
插入一个dynamic block,你需要输入要捕获的column视图的范围或ID
C-c C-c / C-c C-x C-u (org-dblock-update)
更新光标所在的dynamic block. 光标的位置需要在dynamic block的`#+BEGIN`这一行
C-u C-c C-x C-u (org-update-all-dblocks)
更新所有的dynamic blocks. 当你在一个buffer中有多个dynamic block时很有用

你可以在column视图表格中插入公式并且你可以在表格前插入绘图说明–这些操作会随着block的更新而一起更新. 如果表格后面有用`#+TBLFM:`定义计算公式,那么这些公式也会随着block的更新而重新计算

另一个捕获和处理属性值的方法是使用Eric Schulte的`org-collector.el`,这是一个第三方包[fn:62]. 它提供了大量的API来获得某个条目或者某个范围的属性. 并且可以使用任意的Lisp表达式来处理这些属性值然后再插入到表格或者动态区块(dynamic block)中去

属性API :提供給Lisp程序员的属性相关的API

有大量的API提供来获取和修改属性. Emacs Lisp程序员可以使用这些API来编辑属性或实现与这些属性相关的特性. 更多信息参见使用属性API.

日期与时间

为了协助进行项目计划. TODO事项可以加上日期和时间的标签. 这种带有日期和时间信息的特定字符串在Org-mode中被称呼为时间戳(timestamp). 这可能会让人有点迷糊,因为时间戳常常用来标识事情是什么时候创建或改变的. 然而,在Org-mode中,该名称的意义更加广泛

时间戳,最后期限和规划日期 :給事项分配时间

时间戳以一种特定的格式来标识日期(也可能是时间或一个时间段),比如想这样:`”< 2003-09-16 Tue >”[fn:63] ,`< 2003-09-16 Tue09:39 >`,`‘< 2003-09-16 Tue 12:00-12:30 >`[fn:64]. 时间戳可以放在标题和条目的任意位置处. 带有时间戳的条目在agenda视图中会显示在特定的日期区域(参见周/日agenda). 时间戳有以下几种格式:

  • 单纯的一个时间点,一般用于单次的约会,会议等

时间戳最基本的作用就是为某事项分配一个日期/时间. 这就好像在日程表中安排一项日程一样. 当用timeline或agenda视图查看安排时,带有时间戳的事项就会出现在时间戳指示的日期处.

* 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>
  • diary风格的类lisp表达式(Diary-style sexp entries)

要表达更复杂的时间需求, Org-mode可以使用diary风格的类lisp表达式来表示时间,这种表达式是由Emacs内置的calendar/diary包实现的.[fn:65]. 下面是一个例子

* 22:00-23:00 The nerd meeting on every 2nd Thursday of the month
,  <%%(org-float t 4 2)>
  • 时间段

用`–`连接起来的两个时间戳就表示一个时间段. 下面是一个例子

** Meeting in Amsterdam
,   <2004-08-23 Mon>--<2004-08-26 Thu>
  • 无效的时间戳

跟一般的时间戳差不多,只是用方括号代替尖括号. 这种时间戳不会影响事项在agenda中的显示

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

创建时间戳 :插入时间戳的命令

Org-mode中的时间戳必须是复合特定的格式的. 因此Org提供了下面这些命令生成正确格式的时间戳

C-c . (org-time-stamp)

该命令提示你输入日期然后插入对应的时间戳. 如果执行该命令时,光标已经处于时间戳上,则该命令修改时间戳,而不是插入新的时间戳. 如果连续两次成果执行该命令,则插入的是一个时间段.

C-c ! (org-time-stamp-inactive)

类似于C-c . 但是插入的是一个无效的(inactive)时间戳,这种时间戳不会影响事项在agenda上的显示

C-u C-c . /C-u C-c !

类似`C-c .`和`C-c !`,但是包含日期和时间. 默认的时间会自动四舍五入到每5分钟为单位.参见选项`org-time-stamp-rounding-minutes`

C-c C-c
更正时间戳,如果星期数错了或者没有,就会修正或者插入正确的星期数
C-c < (org-date-from-calendar)

插入Calendar窗口中光标所处的日期所对应的时间戳

C-c > (org-goto-calendar)

打开Emacs Calendar窗口并定为到今天. 若光标处于时间戳处,则定为到时间戳表示的位置

C-c C-o (org-open-at-point)

在agenda窗口中打开时间戳所指定的日期或时间段(参见章节周/日agenda)

S-<left> (org-timestamp-down-day) / S-<right> (org-timestamp-up-day)

减少/增加光标所在的日期一天. 这些按键序列与shift-selecton及相关模式相互冲突(参见章节与org-mode冲突的包)

S-<up> (org-timestamp-up) / S-<down> (org-timestamp-down)

更改光标所处的时间戳中的各个部分(年,月,日,时,分). 若时间戳是一个类似‘15:30-16:30’的时间段,则修改第一个时间也会同时改变第二个时间,为的是保持时间跨度不变. 若想修改时间跨度,请直接修改第二个时间. 需要注意的是,若光标不是处于时间戳中,而是处于标题上,则该键序列会修改事项的优先级(参见章节优先级).这些按键序列与shift-selecton及相关模式相互冲突(参见章节与org-mode冲突的包)

C-c C-y (org-evaluate-time-range)

根据时间段计算出时间跨度显示在minibuffer上. 如果带有前缀参数,则将结果写道时间段的后面(若是在表格中,则写到下一列的位置)

日期/时间的提示窗口 :Org-mode是如何帮助你输入日期和时间的

当Org-mode提示输入日期/时间时,会有一个默认值,这个默认值是以缺省的格式来显示的,这给人的感觉似乎只能输入这种特定的格式的时间才行. 其实Org-mode可用处理任何包含有日期/时间信息的字符串,并且很智能的提取出其中的日期/时间信息. 例如你可以使用`C-y`粘贴email中的内容(可能有多行). Org-mode会丢弃任何不符合默认日期/时间格式的字符串,从而提取出其中的日期/时间信息. 提示的默认值一般来说是当前日期,但是如果是在修改一个已经存在的时间戳或者输入时间段的第二个时间戳信息时,默认值使用的是buffer中的哪个时间戳信息. 当输入日期信息时, Org-mode假设大多数时候你想要输入的都是未来的日期,因此如果你没有输入月/年,同时你输入的天/月又比今天要早时,Org-mode会基于”你输入的是未来的日期”这个假设自动填充月/年信息[fn:66]. 如果输入的日期被自动调整到未来的日期,时间提示符会出现`(=>F)`以此来提醒你

举个例子,假设今天是2006年6月13日. 下面列出一些输入和实际解释的对应关系

3-2-5         ⇒ 2003-02-05
2/5/3         ⇒ 2003-02-05
14            ⇒ 2006-06-14
12            ⇒ 2006-07-12
2/5           ⇒ 2007-02-05
Fri           ⇒ nearest Friday (default date or later)
sep 15        ⇒ 2006-09-15
feb 15        ⇒ 2007-02-15
sep 12 9      ⇒ 2009-09-12
12:45         ⇒ 2006-06-13 12:45
22 sept 0:34  ⇒ 2006-09-22 0:34
w4            ⇒ ISO week for of the current year 2006
2012 w4 fri   ⇒ Friday of ISO week 4 in 2012
2012-w04-5    ⇒ Same as above

另外,你还可以输入相对日期,格式是第一个字符用加减号开头,随后是一个用来表示时间长度的数字和一个用来表示天(d)/周(w)/月(m)/年(y)这种时间单位的字符. 如果以一个`+/-`开头,则表示日期是相对于今天来说的. 如果是以两个`+/-`开头,则表示是相对于默认日期来说的. 如果你省略了表示时间单位的哪个字符,则默认为天. 下面是一些例子

+0            ⇒ today
.             ⇒ today
+4d           ⇒ four days from today
+4            ⇒ same as above
+2w           ⇒ two weeks from today
++5           ⇒ five days from default date
+2tue         ⇒ second Tuesday from now.

时间函数能够理解英文中的月份了星期几的缩写形式. 如果你像是用英文全称或其他语言,请配置变量`parse-time-months`和`parse-times-weekdays`

由于当前的Emacs实现并不能合理的表示所有的日期,因此默认情况下Org-mode强制日期的合理区间为1970年-2037年,因为这区间的时间对于所有的Emacs实现都是可处理的. 如果你想使用超过这个时间段的日期,请先阅读变量`org-read-date-force-complatible-dates`的文档字符串

定义一个时间段有两种方式,一中方式是用一个或两个`-`将开始和结束时间连接起来. 另一种是用`+`将开始时间与时间段长度连接起来. 举例子如下

11am-1:15pm    ⇒ 11:00-13:15
11am--1:15pm   ⇒ same as above
11am+2:15      ⇒ same as above

除了minibuffer中的提示符,Org-mode也可能会弹出一个calendar窗口让你选择日期[fn:67]. 在calendar窗口中,你可以通过单击日期或直接安回车的方式选择日期,随后该日期会插入到提示符中去. 你可以在光标不离开minibuffer的同时控制calendar. 命令如下:

<RET>           Choose date at cursor in calendar.
mouse-1        Select date by clicking on it.
S-<right>/<left>     One day forward/backward.
S-<down>/<up>     One week forward/backward.
M-S-<right>/<left>   One month forward/backward.
> / <          Scroll calendar forward/backward by one month.
M-v / C-v      Scroll calendar forward/backward by 3 months.

日期/时间提示符的这些操作看起来很复杂,但是你很快就能适应它们, 随后你会觉得使用其他方式输入日期/时间很不方便. 为了帮助你理解你输入的到底是什么日期,对你输入的实时解释会显示在minibuffer中[fn:68]

定制时间格式 :让时间看起来与众不同

Org-mode使用ISO8601的日期和时间规范. 如果你不习惯此规范想换成其他格式的显示方式,你需要配置变量`org-display-custom-times`和`org-time-stamp-custom-formats`

  • C-c C-x C-t (org-toggle-time-stamp-overlays) 切换客户化定制的日期/时间显示的格式

在输入时间/日期时,Org-mode还是修安排使用默认的格式. 实际上,客户化定制的时间格式并不会正在改变文件中的实际时间格式(存入文件的还是以默认格式存入的). 它只是在显示时转换成客户化定制的格式显示而已. 因此就会造成下面这些后果

  • 你不能把光标移动到时间戳内部了,你只能从时间戳前面直接跳到时间戳的后面
  • `S-<up>`,`S-<down>`不能再用于调整时间戳的内部组件了. 如果光标在时间戳前面,则`S-<up>/<down>`跟`S-<left>/<right>`一样,增减一天. 如果光标在时间戳后面,则时间戳增减一分钟
  • 如果时间段或包含了重复间隔信息的时间戳是不会被转换显示的,还是保留原样
  • 若在表格中包含了日期,则若定制的时间格式比原格式长,表格的对齐会被搞乱,如果比原格式短,则可用正常对齐

最后期限和规划日期 :制定工作计划

  • 最后期限(DEADLINE)

当到达最后期限时,该任务会显示在agenda中. 另外在today这个agenda上也会警示一些快要(由变量org-deadline-warning-days决定提前多少天开始警告)或者已经逾期的任务,该警示会一直持续到任务标识为完成后才消失. DEADLINE的一个例子如下:

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

你可以在设置DEADLINE的同时设置提前多少天发出警示,例如下面的例子表示提前5天发出警示

DEADLINE: <2004-02-29 Sun -5d>    
  • 规划日期(SCHEDULED)

当到达规划日期及之后,该任务会在agenda中一直显示[fn:69]. 另外在today这个agenda上会显示今天距离规划日期已经过去多少天了. 该显示会一直持续到任务被标记为完成状态为止. 下面是一个例子

*** TODO Call Trillian for a date on New Years Eve.
    SCHEDULED: <2004-12-25 Sat>

插入最后期限和规划日期

下面的命令使你可以快速插入[fn:70]最后期限和规划日期

  • C-c C-d (org-deadline) 在标题的下一行插入DEADLINE关键字,该关键字用来标识最后期限信息. 除了插入DEADLINE关键字外,任何CLOSED时间戳都会被删除调. 若调用该命令时带了前缀参数,则表示删除DEADLINE关键字. 根据变量`org-log-redeadline`[fn:71]的值,当更改已经存在的最终期限时,可能会记录日志
  • C-c C-s (org-schedule) 在标题的下一行插入SCHEDULED关键字,该关键字标识了规划日期的信息. 除了插入SCHEDULED关键字外,任何CLOSED时间戳都会被删除. 若调用该命令时带了前缀参数,则标识删除SCHEDULED关键字. 根据变量`org-log-reschedule`[fn:72]的值,当更改已经存在的规划日期时,可能会记录日志
  • C-c C-x C-k (org-mark-entry-for-agenda-action) 标记当前任务为agenda action的目标. 执行该命令后,可以打开agenda或calenda,把光标定位到何时的日期处,然后按下k键,会有一系列的agenda action提供来选择.
  • C-c / d (org-check-deadlines) 创建一颗sparse tree,在该sparse tree中包含了哪些已经超期或者快要超期(根据变量org-deadline-warning-days决定)的任务. 若带有C-u前缀,则显示当前文件中的所有带有deadline的条目. 若带有数字前缀N,则显示N天内超期的和已经超期的条目,例如`C-1 C-c / d`显示所有明天就会超期的条目.
  • C-c / b (org-check-before-date) 创建一颗sparse tree,在该sparse tree中包含了那些最终期限或规划日期在给定日期之前的条目
  • C-c / a (org-check-after-date) 创建一颗sparse tree,在该sparse tree中包含了那些最终期限或规划日期在给定日期之前的条目

注意:org-shedule和org-deadline支持通过指定相对时间来标识日期,例如+1d意思是当前时间戳的下一天,-1w意思是当前时间戳的上一个星期

重复的任务

有些任务是重复性的. Org mode通过在DEADLINE,SCHEDULED或普通的时间戳中放置所谓的`repeater`来标识这种重复性的任务. 例如

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

这里的+1m就是repeater. 意思是每个月重复一次. 如果你需要在一个DEADLINE中同时表明repeater和指定预警期的话,则repeater需要放在前面,预警期放在后面,例如

,DEADLINE: <2005-10-01 Sat +1m -3d>. 

当任务的最后期限和规划时间超期后,就会在agenda中出现. 因此即使标记带有DEADLINE和SCHEDULE的任务为DONE状态就很重要了. 当你将这种任务标记为DONE状态后,该任务就不会在agenda中出现了. 然而这么作带来一个问题,带有repeater的任务被标识为DONE之后,下一个循环的任务不会自动被激活. 为了解决这个问题,Org mode通过如下方法来绕过这个限制:当你使用命令C-c C-t将任务标记为DONE时, 它会将时间戳信息改为下一个重复的时间. 然后将任务标记回为TODO[fn:73].同时原时间戳会被复制并放在deadline的下一行处[fn:74],这样做的目的是保留一个记录告诉你,该任务其实是在上一个循环任务处完结后而来的. 举例来说,如果把上一个例子中的任务标记为DONE,则该任务会变成:

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

当使用`+1m`作为repeater时,循环日期的增加会严格第一个月一个月地进行. 这样的话,假设你连续三个月忘了付账单了,你再把这个任务标记为DONE后,这个任务的deadline只会增加一个月,因此该任务还是被认为是超期的. 另外,还有一些任务–比如说更换电池,它只需要你在最后一次完成任务的时间点之后开始计算重复时间间隔. 为了应付这些情况,Org mode提供了另外两种repeater:`++`和`.+`. 例如

** TODO Call Father
,   DEADLINE: <2008-02-10 Sun ++1w>
,   Marking this DONE will shift the date by at least one week,
,   but also by as many weeks as it takes to get this date into
,   the future.  However, it stays on a Sunday, even if you called
,   and marked it done on Saturday.
** TODO Check the batteries in the smoke detectors
,   DEADLINE: <2005-11-01 Tue .+1m>
,   Marking this DONE will shift the date to one month after
,   today.

若你在某项任务上同时设置了最后期限和规划日期,请保持两者的repater间隔一致.

另一种替代repeater的方法是创建一系列的任务拷贝,每隔拷贝使用不同的日期. 命令`C-c C-x c`可以实现这个功能,参见结构编辑

计时工作时间 :跟踪你在一项任务上花了多少时间

Org mode可以帮助你记录下某项任务花了多少时间. 当你开始工作时,你可以打开计时功能. 当你停止工作或者标识该任务为DONE时,则停止计时并记录下相应的时间间隔. 它还能计算出每项任务所花的总共时间. 同时它还会记录下最近计时任务的历史,这样你可以在这些任务之间快速跳转.

要在不同的Emacs session之间保存计时历史,使用如下配置

(setq org-clock-persist 'history)
(org-clock-persistence-insinuate)

在恢复Emacs后,当你开始对一个新任务进行计时时,此时若有上次未完成的计时[fn:75],则会提示你如何处理,详见分辨空闲时间

计时命令 :开始/停止计时

  • C-c C-x C-i (org-clock-in) 开始对当前任务计时,该命令会插入CLOCK关键字和时间戳. 如果插入的CLOCK不是该任务的第一个计时记录,那么这些CLOCK记录都会放入一个名为`LOGBOOK`的drawer中(由变量`org-clock-into-drawer`设定). 你也可以通过设置`CLOCK_INTO_DRAWER`或`LOG_INTO_DRAWER`属性的方式来覆盖全局设置. 若调用该命令时加了C-u前缀参数,则会让你从最近计时的几个任务中选择一个任务进行计时. 若调用命令时加了两个C-u前缀参数,则会对光标所在的任务开始计时,并把该任务设置为默认任务. 设置为默认任务后,使用C-u前缀参数调用命令时,可以用d来进行选择.

    当计时开始后,mode-line上会显示任务及子任务总计所花的时间和正在计时的任务标题. 如果正在进行的任务需要进行工作量评估参见章节Effort estimates. mode-line上会同时显示预计时间和实际时间[fn:76]. 如果任务是重复任务参见章节Repeated tasks. 则计时只从最后一次重复开始算起[fn:77]. 要进一步控制显示在mode-line上的时间,可以配置属性`CLOCK_MODELINE_TOTAL`. 该属性的值为`current`标示只显示当前的计时实例,值为`today`则显示今天所有任务的统计信息(也可以参见变量`org-extend-today-until`),属性值为`all`则统计所有的计时信息,该属性默认值为`auto`[fn:78].

    在mode-line上点击鼠标左键,会弹出计时选项相关的菜单

  • C-c C-x C-o (org-clock-out) 结束计时. 该命令会在计时开始的那一行插入另一个时间戳并自动计算所花费的时间,然后以`=>HH:MM`的形式插入到两个时间戳之间. 通过配置变量`org-log-note-clock-out`可以在记录clock-out时间戳的同时记录其他附加信息.[fn:79]
  • C-c C-x C-e (org-clock-modify-effort-estimate) 更新当前计时任务的工作量评估信息
  • C-c C-c / C-c C-y (org-evaluate-time-range) 更改时间戳之后重新计算时间间隔. 该命令只在手工修改了时间戳的时候才有用. 如果你用S-<cursor>来更改时间戳,会自动更新时间间隔.
  • C-S-<up/down> (org-clock-timestamps-up/down) 同步增加/减少CLOCK行的结束和开始的时间戳,保持时间段不变
  • C-c C-t (org-todo) 改变正在计时的任务为完成状态会自动停止计时
  • C-c C-x C-x (org-clock-cancel) 取消当前计时
  • C-c C-x C-d (org-clock-display) 展示当前buffer中所有子树的计时统计信息. 该命令会在每隔标题的后面添加上总计的计时时间,每隔总计时间等于该标题下各子标题的总计时间之和. 当你切换到其他buffer(参见变量`org-remove-highlights-with-change`)或按下`C-c C-c`后,该总计时间就会消失

在timeline(参见章节Timeline for a single file)和agenda(参见章节The weekly/daily agenda)模式下,按下`l`键可以查看当天做过哪些任务或者哪些任务今天结束了.

计时报告 :详细报告

Org-mode可以基于计时信息统计出复杂的报表,这种报表是以Org表格的形式展示的,因此也叫做clock table

  • C-c C-x C-r (org-clock-report) 在当前文件插入一个dynamic block,内涵一个clock report. 如果执行命令时光标位于一个已经存在的clock table内,则更新该clock table. 如果执行该命令时带了个前缀参数,则跳到第一个clock report并更新之. The clock table always includes also trees with :ARCHIVE: tag
  • C-c / C-c C-x C-u (org-dblock-update) 更新光标所在的dynamic block. 光标需要位于dynamic block的#+BEGIN这一行
  • C-u C-c C-x C-u 更新所有的dynamic blocks. 如果在buffer中有多个clock table block,则该命令非常有用.
  • S-<left> /S-<right> (org-clocktable-try-shift) 更改当前clock table的:block参数并更新之. 执行该命令时光标需要处于#+BEGIN: clocktable这一行. 如果:block是`today`,则会切到`today-1`,依次类推.

下面是一个clock table的框架

#+BEGIN: clocktable :maxlevel 2 :emphasize nil :scope file
#+END: clocktable

BEGIN行及后面一系列的选项定义了范围,结构和报告的格式. 这些选项的默认值可以通过变量`org-clocktable-defaults`来配置.

第一类选项决定了哪些clock entry会被选入统计

maxlevel    Maximum level depth to which times are listed in the table.
             Clocks at deeper levels will be summed into the upper level.
scope       The scope to consider.  This can be any of the following:
             nil        the current buffer or narrowed region
             file       the full current buffer
             subtree    the subtree where the clocktable is located
             treeN      the surrounding level N tree, for example tree3
             tree       the surrounding level 1 tree
             agenda     all agenda files
             ("file"..) scan these files
             file-with-archives    current file and its archives
             agenda-with-archives  all agenda files, including archives
block       The time block to consider.  This block is specified either
             absolute, or relative to the current time and may be any of
             these formats:
             2007-12-31    New year eve 2007
             2007-12       December 2007
             2007-W50      ISO-week 50 in 2007
             2007-Q2       2nd quarter in 2007
             2007          the year 2007
             today, yesterday, today-N          a relative day
             thisweek, lastweek, thisweek-N     a relative week
             thismonth, lastmonth, thismonth-N  a relative month
             thisyear, lastyear, thisyear-N     a relative year
             Use S-<left>/<right> keys to shift the time interval.
tstart      A time string specifying when to start considering times.
tend        A time string specifying when to stop considering times.
step        week or day, to split the table into chunks.
             To use this, :block or :tstart, :tend are needed.
stepskip0   Do not show steps that have zero time.
fileskip0   Do not show table sections from files which did not contribute.
tags        A tags match to select entries that should contribute.  See
             Matching tags and properties for the match syntax.
  
  

第二类选项指定了table的展示形式. 这些选项默认由函数`org-clocktable-write-default`解释,但是我们也可以使用`:formatter`参数来指定由我们自定义的函数来解释[fn:80]

:emphasize   When t, emphasize level one and level two items.
:lang        Language(80) to use for descriptive cells like "Task".
:link        Link the item headlines in the table to their origins.
:narrow      An integer to limit the width of the headline column in
             the org table.  If you write it like ‘50!’, then the
             headline will also be shortened in export.
:indent      Indent each headline field according to its level.
:tcolumns    Number of columns to be used for times.  If this is smaller
             than :maxlevel, lower levels will be lumped into one column.
:level       Should a level number column be included?
:compact     Abbreviation for :level nil :indent t :narrow 40! :tcolumns 1
             All are overwritten except if there is an explicit :narrow
:timestamp   A timestamp for the entry, when available.  Look for SCHEDULED,
             DEADLINE, TIMESTAMP and TIMESTAMP_IA, in this order.
:properties  List of properties that should be shown in the table.  Each
             property will get its own column.
:inherit-props When this flag is t, the values for :properties will be inherited.
:formula     Content of a #+TBLFM line to be added and evaluated.
             As a special case, ‘:formula %’ adds a column with % time.
             If you do not specify a formula here, any existing formula
             below the clock table will survive updates and be evaluated.
:formatter   A function to format clock data and insert it into the buffer.

  

要得到当天中当前level 1 tree的计时总计信息,你可以这样写

#+BEGIN: clocktable :maxlevel 2 :block today :scope tree1 :link t
#+END: clocktable   

要统计指定的时间段的信息,则可以这样写[fn:81]

#+BEGIN: clocktable :tstart "<2006-08-10 Thu 10:00>"
,                    :tend "<2006-08-10 Thu 12:00>"
#+END: clocktable
,   

要以百分比的形式展示当前子树的计时统计,可以这样写

#+BEGIN: clocktable :scope subtree :link t :formula %
#+END: clocktable

要水平地以紧凑模式来展示至上个星期以来的计时统计,可以这样写

#+BEGIN: clocktable :scope agenda :block lastweek :compact t
#+END: clocktable
,   

识别空闲时间 :识别出你未做工作的空闲时间

如果你正在对某项任务计时,在期间你离开电脑去接了个电话,通常情况下,你需要识别出你离开的那段时间并从计时统计中减去这段时间,或许还需要把这段时间计入其他的计时统计中.

通过配置变量`org-clock-idle-time`的值为某个整数,例如10或15,当你空闲时间超过这么多分钟之后[fn:82],Emacs会提醒你,并询问你要怎么处理这段空闲的时间. 你可以看到空闲时间的长度(不断的持续更新)和一系列的操作选项:

  • k 要将部分或者全部的离开时间计入正在计时的当前任务中,则键入k. Org随后会询问要将其中的多少分钟计入当前任务. 直接按回车表示所有时间都计入当前任务.
  • K 类似k,但会立刻停止对任务的计时
  • s 空闲时间不计入当前任务,并从你离开的时刻接着计时
  • S 类似s,但是会立刻停止计时. 记住无论哪个选项,连上shift键,都会立刻停止计时
  • C 撤销当前的计时统计. 需要注意的是,如果没有用C撤销计时,然而在把离开的时间剔除出去后发现剩余时间少于1分钟,则Emacs也会取消这次计时,这么做的目的是为了防止太多零散的计时统计.

那么,如果想把这段离开的时间作为一项新的计时统计又该怎么处理呢? 只要在减去这段离开时间后立刻对新任务进行计时,Org会注意到你有一段被减去的计时登记在册,然后它会询问是否要将这段计时信息计入新任务的计时中.

还存在这么一种可能,假设你正在对某项任务计时,突然电脑电源被关了,一瞬间,所有的buffer都消失了. 通过emacs的auto-saving机制,你可能恢复了最近的一些Org-mode的改变,包括最后的哪个clock in操作.

在这种情况下,如果你重启了Emacs,并且对任一任务进行计时时,Org会注意到上次session中留有一个悬空的clock in操作,然后Emacs会把该悬空的开始时间戳到现在的这段时间识别为空闲时间,并询问你的下一步操作. 其逻辑和行为与普通的空闲时间一致.

你也可以通过命令`M-x org-resolve-clocks`一次性检查所有在Org Agenda中注册过的Org文件中的悬挂clock in操作.

工作量评估 :提前规划工作成果

如果你习惯以非常细致的方式作计划,或者你需要提供一份进度评估文档,则你会对每个任务进行进度上的评估. 如果你同时对你的工作进行计时,则随后可以对比进度计划与实际所费时间,这是改进进度评估的一个好方法. 评估所需时间的进度信息存储在属性`Effort`中[fn:83]. 你可以用一下命令来为任务设置进度安排(耗时评估)

  • C-c C-x e (org-set-effort)

为当前任务设置进度安排(可以输入一个时间). 如果带有一个数字类型的前缀参数,则表示设置第N个可以的值(具体内容见下文). 也可以在agenda视图中用e快捷键调用该函数

  • C-c C-x C-e (org-clock-modify-effort-estimate)

修改正在计时的任务的耗时评估

很明显,最好是使用Column视图的方式来展示进度评估(参见Column视图). 你可以为耗时评估设定多个值,再加上一个COLUMNS格式属性用来展示这些估计值与相关的计时信息(如果你想要对任务进行计时的话). 例如你可以这样设置:

#+PROPERTY: Effort_ALL 0 0:10 0:30 1:00 2:00 3:00 4:00 5:00 6:00 7:00
#+COLUMNS: %40ITEM(Task) %17Effort(Estimated Effort){:} %CLOCKSUM
  

你也可以全局地设定这两个值,方法是分别设定变量`org-global-properties`和`org-columns-default-format`. 这在当你想在agenda中使用该配置时特别有用.

一种为任务分配耗时评估的方法是切换到column-mode,然后用S-<right>和S-<left>来改变耗时评估的值. 子任务的耗时评估会自动累加到父任务的耗时评估中. 在耗时评估的后一列会显示实际的计时统计信息.

如果你在daily/weekly agenda中切换到column view的话, effort这一列会累加每天的耗时评估[fn:84],你可以使用这项功能来找出计划安排中的空闲时间. 如果想查看指定日期的总体情况,可以设置选项`org-agenda-columns-add-appointments-to-effort-sum`. 则那一天已经开始一段时间的会议也会添加到负荷评估中

耗时评估也可以在secondary agenda filtering(次要日程过滤??)中使用,在agenda中使用`/`键就能出发该过滤功能(参见Commands in the agenda buffer). If you have these estimates defined consistently, two or three key presses will narrow down the list to stuff that fits into an available time slot. (这句话的意思,我是连猜都猜不出来了~)

作记录的同时打开相对计时器 :带计时器的笔记

当作会议纪要时,可能会需要记录会议开始后的xx时间某某发了一个什么言. Org提供了一个相对计时器的功能可以帮助记录xx时间.

C-c C-x . (org-timer)

插入相对时间. 第一次执行该命令时会同时启动相对计时器,并把即使重置为0. 若带了prefix argument则将相对计时器重置为0

C-c C-x - (org-timer-item)

插入一段description list item,同时也记录下相对时间. 若带了prefix argument,则首先将相对计时器重置为0

M-<RET> (org-insert-heading)

一旦已经插入list item,则可以用M-<RET>插入新的list item

C-c C-x , (org-timer-pause-or-continue)

暂停/继续相对计时器

Cu C-c C-x ,

停止相对计时器. 之后你就只能重新开始一个新计时器了. 该命令也会把计时器从mode-line上移除

C-c C-x 0 (org-timer-start)

重置相对计时器,但并不将相对时间插入到buffer中. 默认情况下相对计时器重置为0,但可以带C-u的方式来重置相对计时器到特定的开始时间. 使用C-u C-u双prefix argument的方式调用该命令,则会同时对选中范围的所有相对时间信息进行修改.

倒计时计时器 :为任务倒计时

在Org-mode下运行`org-timer-set-timer`会调起一个倒计时计时器. 若你在agenda buffer中可以用键`;`调用,其他情况下可以用键序列`C-c Cx ;`.

命令`org-timer-set-timer`会提示用户输入倒计时的时间,然后在mode-line上显示倒计时的信息. 变量`org-timer-default-timer`设置了默认的倒计时的时间值. 使用prefix numeric argument会覆盖该值.

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

任何一个整理系统都需要具有快速快速捕获创意和任务,并将其与相关资料链接的能力. Org为该功能实现了名为capture的流程. 它还能够将任务(附件)相关的文件存储在某个特定目录下. 在这套系统中,被处理的对象是任务和项目. 通过将已完成的项目整个移动到归档文件中,可以保持系统的紧凑和快速.

Capture :捕获新事物

Capture使得你能够在几乎不打断工作流的情况下快速存储记录. Org捕获新事物的方式深受John Wiegley的remember.el的影响. 自从version6.36开始,org通过配置与remember.el协同工作,随后用org-rembember.el替代rembember.el. 到了8.0版本,org-remember.el完全被org-capture.el所代替.

如果你的配置文件还是以org-remember.el为基础进行配置的,则你需要用一下方法来升级你的配置文件. 要转换你的org-remember-templates变量,执行命令

M-x org-capture-import-remember-templates,然后保存org-capture-templates的值

配置capture :记录保存在哪里?

下面的配置设置了一个默认的记录文件并且定义一个全局热键[fn:85]来捕获新资料.

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

使用capture :调用和结束capture的命令

C-c c (org-capture)
注意,该键绑定是全局性的,然而默认情况下却没有激活:你需要手工安装该键绑定. 如果你定义了capture模板,则它会提示你选择其中一个模板或这使用默认模板,当你选择了某个模板后会进入一个新的capture buffer. 随后你可以在其中输入要保存的信息.
C-c C-c (org-capture-finalize)
在capture buffer中输入完了要保存的信息后,按C-c C-c会保存记录并退出capture buffer,并且会还原capture前的工作状态,这样你可以继续以前的工作. 若带有prefix arg,则该命令保存好记录后,会跳转到保存新记录的地方.
C-c C-w (org-capture-refile)
使用refile(参见Refile and copy)流程代替capture流程. 该命令实际执行的是普通的refile命令,因此执行该命令时需要注意光标所在的位置. 该命令会把接收到的prefix argument传递給org-refile命令
C-c C-k (org-capture-kill)
取消capture这个动作,还原到之前的状态

在agenda中按k键也可以调用org-capture命令. 通过这种方式调用的org-capture,模板中的日期会插入agenda中光标所处的日期,而不是当前日期.

要找到最后存储的capture的位置,使用带prefix arg的org-capture命令

  • C-u C-c c

    定位到指定capture模板的最后存储位置

  • C-u C-u C-c c

    在当前buffer地打开最后一次capture存储的位置

要在当前buffer插入capture的记录,使用C-0 prefix argument来调用org-capture命令

capture模版 :定义不同类型记录的大纲结构

你可以为不同类型的记录定义不同的模板和存储位置. 创建模板的最简单的方法就是通过customize界面进行.

  • C-c c C

    用customize界面自定义变量`org-capture-templates`

在对模板定义进行正式描述之前,让我们来看一个例子. 假设你向定义一个模板来创建一个TODO事项,创建的TODO事项放到名为`Tasks`的heading下并存储在文件`~/org/gtd.org`中, 同时你需要捕获日记并以datetree的形式存入journal.org中,则你可以使用下面的配置信息.

(setq org-capture-templates
      '(("t" "Todo" entry (file+headline "~/org/gtd.org" "Tasks")
         "* TODO %?\n  %i\n  %a")
        ("j" "Journal" entry (file+datetree "~/org/journal.org")
         "* %?\nEntered on %U\n  %i\n  %a")))

这时,如果你按下C-c c t,Org会自动生产一个模板:

	* TODO
     [[file:link to where you initiated capture]]

在扩展模板时,%a的表示你调用capture命令时的位置链接. 当你从email中派生任务时,该链接就特别有用.

要为某个特定的模板定义快捷键而不用经过模板选择界面,你可以这样定义键绑定:

(define-key global-map "\C-cx"
  (lambda () (interactive) (org-capture nil "x")))

组成模板的各个元素 :一个完整的模板有哪些部分组成

现在让我们来看看模板定义中的各个元素. `org-capture-templates`中的每个entry都是一个列表,由下面几个部分组成:
  • Keys

    keys用来选择某个特定的模板,它是一个由字母组成的字符串,例如”a”表示按下a键就会选择对应的模板,而”bt”表示按下”bt”这两个键会选择对应的模板. 拥有相同prefix key的keys必须依次排列在list中,并且预先要有一个由2个元素组成的entry来解释prefix key. 下面是一个解释prefix key的entry的例子

    ("b" "Templates for marking stuff to buy")
        

    若你没有手工将”C”定义为某个模板的key,则它会用来自定义`org-capture-templates`变量.

  • description

    关于模板的简短描述,会在选择template界面上显示.

  • type

    type为一个symbol,有效值为:

    • entry

    表示Org-mode下的一个heading节点. 若target中定义了节点,则会在target节点下创建子节点,否则创建一个顶级节点. 这里target文件必须是一个Org-mode文件.

    • item

    表示plain list item. 会添加在target location下的第一个plain list位置处. 同样的,target file必须是Org文件

    • checkitem

    类似item,但是它表示checkbox item

    • table-line

    表示表格的一行. 它会添加到target location的第一个表格中. 根据属性(下面会提到)为`:prepend` 和`:table-line-pos`的不同,决定该行放置在表格的具体哪个位置.

    • plain

    纯文本

  • target

    指定被捕获的记录所存放的位置. 在Org-mode文件中,targets通常定义为一个node,被捕获的entry放到该node下. 它还可以是一个table或者是一个list. 大多数target定义时都会包含一个文件名. 但若该文件名为空字符串,则默认使用`org-default-notes-file`表示的文件. 该指定的文件不仅可以由变量指代,还能由函数,Emacs Lisp Form指代.

    target的可选格式有:

    • (file “path/to/file”)

    被捕获的内容会被放置在file的开头/结尾处

    • (id “id of existing org entry”)

    被捕获的内容作为该entry的子节点,或插入到entry的body中

    • (file+heading “path/to/file” “node heading”)

    被捕获的内容放置在该file的指定heading下,但需要保证指定的heading在file中是唯一的.

    • (file+olp “path/to/file” “level 1 heading” “level 2 heading” …)

    若file中存在同名的heading,则使用该方法加以明确

    • (file+regexp “path/to/file” “regexp to find location”)

    使用正则表达式来定位

    • (file+datetree “path/to/file”)

    在date tree上用今天的日期创建一个heading

    • (file+datetree+prompt “path/to/file”)

    在date tree上用指定的日期创建一个heading,会提示你输入日期

    • (file+function “path/to/file” function-finding-location)

    用函数来定位

    • (clock)

    定位到正在被计时的entry处

    • (function function-finding-location)

    用函数来定位存储文件和位置

  • template

    模板内容. 若内容为空,则会使用默认的模板内容. 模板内容可以是一个字符串,也可以通过(file “path/to/template”)这样的语法表示从外部文件中读取模板内容.

  • properties

    剩下的内容是一些附加属性list:

    • :prepend

    通常情况下,新捕获的内容会附加在target location的后面,而该属性会添加在target location的前面

    • :immediate-finish

    该属性表示不需要显示capture buffer给用户输入更多的信息.直接返回就好. 若所有的信息都能够通过模板变量自动获得的情况下可以使用

    • :empty-lines

    插入新捕获的内容时,前后空出多少个空行.

    • :clock-in

    为新捕获的item开始计时

    • :clock-keep

    若设置了clock-in,则在capture动作完成后,依然保持计时器的继续运行

    • :clock-resume

    若capture操作中断了对之前任务的计时,则在完成capture操作之后继续对之前任务进行计时.

    需要注意的是,:clock-keep的优先级高于:clock-resume,若两者都设置为t,则当前计时器会启动,而前一个计时器不会继续运行.

    • :unnarrowed

    不要narrow target buffer,显示target buffer的所有内容. 默认情况下会narrow target buffer,让它只显示捕获新事物的那节点内容

    • :table-line-pos

    设置capture的内容插入到table的位置. 它的格式类似于”II-3”,表示它是表格中第二部分(以-------分隔)的第三行

    • :kill-buffer

    若target file是未打开的状态,则在capture完成之后,自动kill掉新打开的buffer

模板扩展 :插入时间和上下文的相关信息

模板内容中可以有一些以%[fn:86]开头的特殊变量,当对模板进行扩展时,会动态插入它所表示的值

%[file]插入file的内容能够
%(sexp)插入sexp的返回值,sexp必须返回字符串
%<…>按…表示的格式插入时间戳信息....的格式参见format-time-string函数说明
%t插入日期
%T插入日期与时间
%u, %U类似%t和%T,但是插入的时间戳是inactive的(以[]括起来的)
%a注释,一般情况下是函数org-store-link创建的链接.
%i若调用capture命令时,有选中内容,则插入选中内容
%A类似%a,但会提示输入链接的描述部分
%ckill-ring中的当前内容能够
%x粘贴板的内容
%k当前正在计时的任务title
%K当前正在计时的任务的链接
%n用户名,变量(user-full-name的值
%fcapture命令调用时当前buffer所对应的文件名
%F类似%f,但显示全路径
%^g提示输入tag,使用target file中的tags列表作为可选项
%^G提示输入tag,使用agenda中所有注册的file中的tags列表作为可选项
%^t类似 %t, 但是会提示你输入日期. 同样的还%^T, %^u, %^U. 这几个变量. 还可以用类似%birthdayt这样的格式来为提示做出说明
%^CInteractive selection of which kill or clip to use.
%^LLike %^C, but insert as link.
%propp提示用户为名为prop的属性赋值
%prompt提示用户输入某个字符串. 还可以为用户提供默认值和补全值,格式为%prompt竖线default竖线completion2竖线completion3…. 使用方向键可以选择历史数据

还有一些变量是与特定的link type[fn:87]所特有的

Link typeAvailable keywords
bbdb%:name %:company
irc%:server %:port %:nick
vm, wl, mh, mew, rmail%:type %:subject %:message-id
%:from %:fromname %:fromaddress
%:to %:toname %:toaddress
%:date (message date header field)
%:date-timestamp (date as active timestamp)
%:date-timestamp-inactive (date as inactive timestamp)
%:fromto (either “to NAME” or “from NAME”)[fn:88]
gnus%:group, for messages also all email fields
w3, w3m%:url
info%:file %:node
calendar%:date

要定义扩展模板后,光标所在的位置,用%?表示光标的位置.

与上下文相关的模板 :只在特定的上下文环境中显示模板

通过定义变量`org-capture-templates-contexts`可以让模板只在特定的上下文环境中才有效.

Attachments :为任务增加附件

通常我们会为任务/节点添加相关材料. 少量的纯文本说明可以存储在节点内. 使用超链接可以连接到云端/本地的其他文件上.

还有一种方法就是为任务/节点添加附件. 所谓附件是指存储在outline node所属目录中的文件. Org使用每个entry的unique ID作为目录名称,这些目录存放在org文件所属目录的data子目录下. 若该目录纳入了git版本控制中,则org会在目录发生改变后,自动commit

文件和目录都可以作为附件添加到某个entry上. 甚至还可以让子节点继承父节点的attachment directory(存放附件的目录),这样整个子树都使用相同的存放附件的目录

下面是附件相关的命令

  • C-c C-a (org-attach)

为entry添加附件的同一接口,该命令会提示你选择用哪种方法为entry添加附件

  • a (org-attach-attach)

选择附件文件,并将它移动到该entry存放附件的目录中. 根据变量`org-attach-method`的不同,附件会拷贝/移动/链接到attachment directory中. 需要注意的是,不是所有的操作系统都支持硬链接.

  • c/m/l

    指定用拷贝/移动/链接的方式将附件存放在该entry存放附件的目录中.

  • n (org-attach-new)

    创建一个Emacs buffer作为新附件

  • z (org-attach-sync)

    同步attachment directory中的附件信息. 若你手工添加了附件到attachment directory中则该命令很有用

  • o (org-attach-open)

    打开当前entry的附件. 若有多个附件,则会提示你具体打开那个附件. 用来打开附件的程序由变量`org-file-apps`决定.

  • O (org-attach-open-in-emacs)

    类似o,但是强制用emacs打开附件

  • f (org-attach-reveal)

    打开当前entry用来存放附件的目录

  • F (org-attach-reveal-in-emacs)

    类似f,但是前置用emacs的dired打开目录

  • d (org-attach-delete-one)

    删除某个附件

  • D (org-attach-delete-all)

    删除该entry的所有附件. 一个更安全的方法是用dired打开存放附件的目录,然后手工删除所有附件

  • s (org-attach-set-directory)

    为该entry设置指定的目录作为存放附件的目录. 该命令通过为entry设置ATTACH_DIR属性来完成这一任务.

  • i (org-attach-set-inherit)

    设置ATTACH_DIR_INHERIT属性,这样所有的子节点会使用父节点的attachement directory

RSS Feeds :从RSS Feeds中获取输入

通过配置`org-feed-alist`的至,Org可以根据RSS feeds和Atom feeds中的数据新增/改变entry的内容。下面是一个配置的例子

(setq org-feed-alist
      '(("Slashdot"
         "http://rss.slashdot.org/Slashdot/slashdot"
         "~/txt/org/feeds.org" "Slashdot Entries")))

上面的例子会使得rss.slashdot.org的feed中的item同步到文件~/org/feeds.org的名为`Slashdot Entries`的heading下。

下面是一些相关的命令

  • C-c C-x g (org-feed-update-all)

    同步org-feed-alist中配置feeds的item到Org文件中

  • C-c C-x G (org-feed-goto-inbox)

    提示你输入一个feed的名称,然后跳转到对于的Org文件

在同名的heading下,Org会创建一个名为`FEEDSTATUS`的drawer,并在其中存储关于feed中item的状态,这样就能避免同一个item多次添加的情况出现。 因此你需要添加`FEEDSTATUS`到Org文件的drawer列表中。例如

#+DRAWERS: LOGBOOK PROPERTIES FEEDSTATUS

更详细的信息请阅读org-feed.el和org-feed-alist的docstring

Protocols :从外部程序(例如浏览器)获取信息

外部程序可以根据一定的协议规则通过emacsserver向Org传递要处理的消息。 详细信息请参见 http://orgmode.org/worg/org-contrib/org-protocol.php

Refile and copy :移动/拷贝tree从一个地方到另一个地方

当回顾捕获到的资料时,常常会对资料进行整理。若要手工完成那些剪切,定位,复制操作则显得太繁琐了。Org提供了以下一些命令帮助我们完成整理的动作

  • C-c C-w (org-refile)

    移动当前entry/region到其他地方。 该命令会告诉你有哪些可以被转移的位置(target)可选,并提供相关的补全功能。 被移动的item(或region中所有的item)会移动到target heading下作为它的子节点。 而根据变量`org-reverse-note-order`的值的不同,可能是作为第一个子节点或最后一个子节点。

    默认情况下,被转移到的target位置为当前buffer的一级heading,但是你也可以自定义target到其他文件。要了解详细信息,请参见变量`org-refile-targets`. 若你希望在选择target location时以路径的方式表示文件内的heading(例如file.org/Heading1/heaindg2表示file.org中的一级标题heading1下的二级标题heading2),请配置变量`org-refile-use-outline-path`和`org-outline-path-complete-in-steps`。 如果你希望移动到一个不存在target location时可以新建node,则配置变量`org-refile-allow-creating-parent-nodes`。 若设置了变量`org-log-refile`,则当一个entry被refile时会记录下当前的时间戳信息。

  • C-c M-w (org-copy)

    类似org-refile,但源entry/region不会被删除

  • C-u C-c C-w

    使用refile界面来跳转到target的heading处

  • C-u C-u C-c C-w (org-refile-goto-last-stored)

    跳转到最后refile的target location

  • C-2 C-c C-w

    把entry/region移动到正在计时的item之下

  • C-3 C-c C-w

    移动entry时保留原entry在原处(Refile and keep the entry in place.) 通过配置变量`org-refile-keep`可以设置该动作为refile的默认动作。 不过需要注意的是,该操作可能会导致重复的ID属性。

  • C-0 C-c C-w / C-u C-u C-u C-c C-w (org-refile-cache-clear)

    清理target cache。 通过设置变量`org-refile-use-cache`可以开启缓存refile target的功能。 开始了该功能后,需要用该命令清空refile target缓冲区才能让命令看见新的refile target

Archiving :处理已完成的项目

若某个项目完成了,你可能会把代表该项目的tree移开,不要让它再在agenda中出现。 该动作由归档命令来完成。

  • C-c C-x C-a (org-archive-subtree-defaut)

    使用变量`org-archive-defaullt-command`中定义的命令对当前entry进行归档

移动tree到另一个归档文件中

最常用的归档动作是将某project tree移动到另一个归档文件中

  • C-c C-x C-s / C-c $ (org-archive-subtree)

    将光标位置为起始位置的子树归档到变量`org-archive-location`指定的位置

  • C-u C-c C-x C-s

    检查当前headline是否有可以归档的直接子节点。 Org通过对每个subtree检查是否有未完成事项,若未找到,则该命令提示你是否将其归档。 若调用该命令时光标不在headline的位置,则第一级的tree会被检查。

默认情况下,归档的地址是同一目录下的当前文件名后接`_archive`的文件。你也可以为某个heading指定单独的归档地址。更详细的信息请参见变量`org-archive-location`的docstring。

也可以为单个buffer设置该变量的值,例如

#+ARCHIVE: %s_done::

若你想为单个的entry或subtree定义自己的归档地址,则给他们定义名为`:ARCHIVE:`属性,并使用归档地址作为其值

subtree被归档时,同时会有大量的属性记录下当时的上下文信息。例如被归档的entry所属的文件,大纲路径,归档时间等。 可以通过配置变量`org-archive-save-context-info`来调整有哪些附加信息会在归档时被记录

内部归档

若你只是不想让某个subtree不出现在agenda,但是又不想把它移动到其他文件中,你可以使用ARCHIVE tag

带有ARCHIVE tag的headline具有以下几个特点

  • 使用visiblitiy cycling命令不会展开该headline. 若你想强制展开该headline,则可以使用C-TAB,或者设置选项`org-cycle-open-archived-trees`. 当然像`show-all`这样的普通outline命令也会展开被归档的subtree
  • 在agenda试图中不会显示被归档tree的内容,除非你配置了选项`org-agenda-skip-archived-trees`. 当然,在agenda中,你也可以使用v a来临时把归档tree的内容显示进来
  • 被归档的tree在导出时只会导出headline而不会导出内容. 具体细节参见变量`org-export-with-archived-trees`
  • 被归档的tree不会在column视图中显示,除非变量`org-columns-skip-archived-tree`的值为nil

下面是操作ARCHIVE标签的命令

  • C-c C-x a (org-toggle-archive-tag)

    为当前headline添加/去除ARCHIVE标签. 当设置了ARCHIVE标签后,该headline变为灰色,其内容也被隐藏

  • C-u C-c C-x a

    检查当前headline下的是否有哪个直接子节点可以被归档. 类似C-u C-c C-x C-s

  • C-TAB (org-force-cycle-archived)

    即使是被归档的tree也会被展开

  • C-c C-x A (org-archive-to-archive-sibling)

    移动当前entry到Archive Sibling下. 该sibling名为`Archive`,且带有`ARCHIVE`标签.

Agenda视图

鉴于Org的工作方式,待办事项,定时事项,各种带标签的headline被分散到各个Org文件中. 要查看整个整体的情况,就需要把这些分散的信息整合起来.

Org可以根据各种条件从各个分散的Org文件中抽取出复核条件的内容,并在一个新buffer中显示. Org为此提供了多种不同的类型的视图:

agenda
它看起来跟日历类似,并能显示特定日期的相关信息
TODO list
显示所有未完成的事项
match view
显示标签,属性,工作状态符合匹配条件的事项
timeline view
将某个Org文件的所有事项按时间排序
text search view
从多个文件中查找包含指定关键字的所有事项
stuck projects view
显示没有继续前进的项目
custom view
自定义搜索,它可以结合多种不同的视图

这些抽取出来的信息会同一展现在一个名为`agenda buffer`的特别buffer中. 该bufer是只读的,但是提供了访问/修改对应原Org文件内容的命令.

有两个变量控制了agenda buffer是如何显示的,以及agenda退出时,是否还原之前的窗口配置状态. 这两个变量分别为`org-agenda-window-setup`和`org-agenda-restore-windows-after-quit`

Agenda files :从哪些文件中搜索提供給agenda展示的信息

agenda视图从agenda文件中抽取数据来展示,所谓agenda文件是指列在变量`org-agenda-files`中的文件. 如果agenda文件为一个目录,则表少该目录下所有的org文件都为agenda文件.

因此,即使你只使用一个org文件,也需要把该文件列入变量`org-agenda-files`中. 你可以手工修改该变量,但Org也提供了很多方便的命令方便你维护该变量

  • C-c [ (org-agenda-file-to-front)

添加当前文件到`org-agenda-files`的首部. 若当前文件以及在变量`org-agenda-files`中了,则将它移动到首部. 使用prefix argument调用该命令,则会添加/移动到变量`org-agenda-files`的尾部

  • C-c ] (org-remove-file)

将当前文件从`org-agenda-files`中删除

  • C-’ / C-, (org-cycle-agenda-files)

循环遍历agenda文件列表(org-agenda-files),打开其中的org文件

  • org-iswitchb

使用类似iswitchb的界面来在各org buffer之间切换

Org=>File list for agenda菜单列出了当前agenda文件列表中的所有org文件,你可以用该菜单访问这些org文件

若你只想查看某个文件甚至是某个文件的部分subtree的agenda视图,而不管该文件是否在agenda文件列表中,你可以在agenda面板显示时按下一次或多次的<键. 若想永久限制agenda的范围,可以使用以下命令:

  • C-c C-x < (org-agenda-set-restriction-lock)

永久性的限制agenda范围为当前subtree. 若待用该命令时带了prefix argument或者光标在第一个headline的之前时,agenda的范围被限制为整个这个文件. 若调用该命令时已经有window展示了agenda视图,则新的限制立刻作用在该agenda视图上.

  • C-c C-x > (org-agenda-remove-restriction-lock)

删除由C-c C-x >所创建的限制.

若你启用了speedbar,则在speedbar frame中还能使用以下命令

  • < (org-speedbar-set-agenda-restriction)

永久性的约束agenda视图范围,类似C-c C-x <

  • > (org-agenda-remove-restriction-lock)

删除<产生的约束,类似C-c C-x >

Agenda dispatcher :调用agenda视图的面板

各种agenda视图都是通过一个同一的agenda面板来调用的,这个agenda面板推荐绑定到一个全局键序列上(推荐C-c a). 在angenda面板上提供了如下命令来调用不同的agenda视图:

a

创建类似日历那样的agenda视图(agenda) (参见Weekly/daily agenda)

t / T
创建代办事项列表(TODO list)(参见Global TODO list)
m / M
显示标签,属性,工作状态符合匹配条件的事项(match view)
L
为当前buffer创建timeline view
s
显示匹配/不匹配某关键字表达式/正则表达式的事项
/
使用`multi-occur`命令来对变量`org-agenda-files`和`org-agenda-text-search-extra-files`中所列出的文件进行正则查找. 使用prefix argument可以定义每次查找匹配多少行,默认为1行
# 或 !
显示无进展的project
<

限定接下来调用的agenda视图的显示范围为当前buffer

<<
如果有active region,则该命令限制接下来agenda视图的显示范围为该region. 否则显示接下来要显示的agenda视图的范围为当前的subtree
*
开启/关闭sticky agenda views. 默认情况下,Org只维护唯一的一个agenda buffer. 当你更改agenda view时,该buffer会自动更新显示新的agenda view的内容. 若你经常在不同的视图之间切换,则更新agenda buffer会消耗大量的时间和资源. 通过开启sticky agenda view(通过配置变量`org-agenda-sticky`可以默认打开该行为),Org会停止agenda buffer的自动更新,你需要手工按r或g来手动更新agenda buffer的内容. 此外,在任何使用都可以通过运行`org-toggle-sticky-agenda`来切换sticky agenda view

出了内置的agenda视图,你还可以自定义自己的agenda视图,并通过agenda面板进入自定义的agenda视图.

Built-in agenda views :哪些agenda视图是天然可用的

该章节,我们描述哪些Org内建的agenda视图

Weekly/daily agenda :带任务信息的日历

Weekly/daily agenda看起来就像是一张日程表似的,它显示了当前周/日的所有任务.

  • C-c a a (org-agenda-list)

    从一系列Org文件中抽取当前周的信息并以日程表的形式展现出来. 该日程表展示了每一天的事项. 使用numeric prefix argument(比如C-u 2 1 C-c a a),可以设置生成的日程表显示多少天的事项

    若不带numeric prefix argument调用该命令,则默认显示的天数由变量`org-agenda-span`决定,该变量的值可以是数字N表示N天,也可以是类似day,week,month,year这样的值. 默认该值为week,这时默认的显示起始时间为前一个周一(参见变量`org-agenda-start-on-weekday`). 你也可以用时间偏移值来表示时间的开始日期,例如(setq org-agenda-start-day “+10d”)表示以10天后的日期作为起始日期.

agenda buffer还提供了很多远程编辑原Org文件的命令,这些命令的详细说明请参见Agenda commands

与Calendar/Diary整合在一起

Calendar与Diary的功能与Org非常互补,若能将Org的输出与diary整合起来将是十分受用的.

要让Org-mode的agenda也能显示Emacs diary中的事务,需要作如下配置

(setq org-agenda-include-diary t)

做了如上的配置之后,包括假期,纪念日等等,所有的diary事项都会在agenda视图中显示出来. 在agenda buffer中可以使用<SPC> <TAB> <RET>来跳转到diary文件. 使用i命令创建一个今日事项. 使用S命令查看日出/日落的时间,M来看月相,C用来转换历法格式. c用来在agenda和calendar之间切换

Org甚至不用做任何配置就天然支持diary sexp entry. 下面是一个例子

* Birthdays and similar stuff
  #+CATEGORY: Holiday
  %%(org-calendar-holiday)   ; special function for holiday names
  #+CATEGORY: Ann
  %%(org-anniversary 1956  5 14) Arthur Dent is %d years old
  %%(org-anniversary 1869 10  2) Mahatma Gandhi would be %d years old

从BBDB中读取周年纪念日

要使Org在agenda视图中显示存储于BBDB的周年纪念信息,你只需要添加如下代码到Org文件中

* Anniversaries
  :PROPERTIES:
  :CATEGORY: Anniv
  :END:
  %%(org-bbdb-anniversaries)

Appointment reminders

通过使用命令`org-agenda-to-appt`,Org可以使用Emacs appointment的通知功能. 该命令默认从agenda files文件中抽取带有起始时间(时间不能只精确到日,一定要精确到几点几分),结束时间,时间戳信息的entry,并添加到appointment中. 另外,你也能够只抽取哪些处于特定的分类,匹配特定的正则的entry(具体信息参见命令`org-agenda-to-appt`的docstring). appointment会提前一段时间发出提醒,这个提前的时间默认由变量`appt-message-warning`决定,但若agenda files中的entry定义了`APPT_WARNTIME`属性,则使用该属性值代替.

Global TODO list :显示所有未完成的事项

Global TODO list视图将所有未完成的事项整合在一个地方显示.

  • C-c a t (org-todo-list)

    该命令进入Global TODO list视图,该视图从agenda files中抽取所有未完成事项并展示在一个buffer中. 此外该buffer为agenda-mode,你可以直接使用agenda命令来查看/处理这些未完成事项

  • C-c a T (org-todo-list)

    类似C-c a t .但支持只选择特定TODO关键字的事项.

    当调用该命令时会提示你你输入TODO关键字,你也可以用`|`同时选择多个TODO关键字.

    若调用该命令时带了numeric prefix argument,则会选择`org-todo-keywords`中的第N个todo关键字.

    在该视图中,可以使用r来刷选显示. 也可以使用N r来刷新第N个TODO关键字.

在该视图模式下,还可以通过单击某个按键来更改原Org文件中的待办事项的完成状态.

默认情况下,该视图会将所有的未完成事项都列出来,这使得列表会非常长. 有两种方式进行更进一步的筛选

  • 若想根据entry的scheduled,deadline,timestamp来进行过滤,配置如下变量`org-agenda-todo-ignore-scheduled`,`org-agenda-todo-ignore-deadlines`,`org-aegnda-todo-ignore-timestamp`和`org-agenda-todo-ignore-with-date`
  • 若想只显示最高层次的TODO headline,而不现实sublevel的TODO entry,配置变量`org-agenda-todo-list-sublevels`

Matching tags and properties :依规则搜索事项

如果agenda files中的headline标记了tags 和properties,则你可以根据这些元数据作为匹配条件来抽取事项. 这里使用的匹配规则语法与创建sparse tree时使用的语法是一样的.

  • C-c a m (org-tag-view)

    该命令抽取出tag符合给定tag集合的事项. 该命令会提示你输入选择条件,该选择条件是关于tag的逻辑表达式,像`+work+urgent-withboss`这样或`work|home`这样(具体语法请参见tags). 若你经常使用某个条件作为查询条件,你可以自定义一个命令来专门进行这种查询(方法参见Agenda dispatcher)

  • C-c a M (org-tags-view)

    类似C-c a m, 但是搜索的范围只局限于未完成的事项,并且强制检查子事项(参见变量`org-agenda-tags-todo-honor-ignore-options`). 要排除scheduled / deadline事项,配置变量`org-agenda-tags-todo-honor-ignore-options`. 若想同时对TODO关键字和tag作匹配筛选,请参见tag searches

要了解tags list视图中的可用命令,请参见Agenda commands

匹配语法(Match syntax)

搜索字符串可以使用布尔运算. `&`表示`与`,`|`表示`或`. 并且`&`的优先级要高于`|`,而且不能用使用括号. 查询字符串中的每个要素可以是要匹配的tag或是一个类似带比较操作符的`PROPERTY OPERATOR VALUE`的表达式. 在元素前家`-`表示不能匹配,而`+`则是主动选择(positive selection?)的语法糖. 当使用`+`或`-`时,不需要使用`&`来表示`和`的关系. 下面是一些根据tag选择的例子

‘work’
    Select headlines tagged ‘:work:’.
‘work&boss’
    Select headlines tagged ‘:work:’ and ‘:boss:’.
‘+work-boss’
    Select headlines tagged ‘:work:’, but discard those also tagged ‘:boss:’.
‘work|laptop’
    Selects lines tagged ‘:work:’ or ‘:laptop:’.
‘work|laptop+night’
    Like before, but require the ‘:laptop:’ lines to be tagged also ‘:night:’.

查询条件除了使用tag名外,还能在大括号中使用正则表达式. 例如`work+{^boss.*}`会匹配同时包含`:work:`标签和一个以上以`boss`开头的标签的headline

类似于正则表达式,group tag也会被扩展. 例如,假设`:work:`是`:work:lab:conf:`的group tag,则搜索`work`会扩展为`{\(?:work\|lab\|conf\)}` ,而`-work`会被扩展为`-{\(?:work\|lab\|conf\)}`

在匹配tag的同时,你还可以根据headline的属性值(property)来作匹配. 不仅可以对真正的property进行测试,还可以对一些特殊的property进行测试. 例如:`TODO`属性表示entry的TODO关键字,而`PRIORITY`属性表示entry的PRIORITY关键字. 目前暂不支持`ITEM`这个特殊的property

除了实际property和特殊peroperty外,还有另外一种peroperty:`LEVEL`,它用来指定搜索entry的级别. 也就是说以条件`+LEVEL=3+boss-TODO=”DONE”`会列出所有第三级别的,带有tag`boss`的,且TODO关键字为`DONE`的headline. 对于那些设置了`org-odd-levels-only`的buffer来说,`LEVEL`并不与标题前的*个数相匹配了,这时`LEVEL=2`对应3个*,`LEVEL=3`对应5个*,依次类推

下面是其他的一些例子:

`work+TODO=”WAITING”`

搜索带:work:标签,且TODO关键字为`WAITING`的事项

`work+TODO=”WAITING”|home+TODO=”WAITING”`

查询work/home中处于wating状态的任务

当对属性值进行匹配测试时,可以使用大量的操作符. 下面是一些更复杂的例子:

+work-boss+PRIORITY="A"+Coffee="unlimited"+Effort<2+With={Sarah\|Denny}+SCHEDULED>="<2008-10-11>"

不同的属性值有不同的比较符:

  • 若属性值为数字,则可以使用数字比较符`<`,’','>','<’,’>=’,’<>’
  • 若属性值包含在”“中,则属性值为字符串,可以使用字符串相关的比较符和操作符
  • 若属性值包含在”<>”中(比如`DEADLINE<=”< 2008-12-24 18:30>”`),则属性值被认为是日期/时间格式,可以使用与时间相关的比较符. 还有一些特殊的属性值比如”<now>”表示当前的时间. “<today>”,”<tomorrow>”表示今天/明天的0:00时分. 还有”<+5d>”,”<-2m>”,”<+3y>”这样的写法
  • 若属性值包含在{}中,则表示正则表达式,这时可以用`=`表示匹配正则表达式或”<>”表示不匹配正则表达式

一般来说,通过TODO,LEVEL和CATEGORY属性进行匹配的速度快,其他的属性进行匹配的速度慢. 但若你对某事项的一个属性进行了匹配操作,则对该事项的其他属性进行匹配会快速的多.

你可以配置Org mode,使之在搜索时开启属性继承的功能,但是要小心,这项功能会大幅度降低查询速度. 具体细节请查看属性继承

为了向下兼容,也为了方便输入搜索式,还存在另外一种方法来匹配TODO状态. 方法是,用`/`将搜索匹配表达式分成前后两部分,前一部分为搜索tag和property的表达式,后一部分用来专门匹配TODO状态. 后一部分的语法跟tag匹配的语法类似,但有一点要注意,用AND逻辑符组合多个必选的TODO关键字是没有意义的,而用AND逻辑符组合的多个排除的TODO关键字是有意义的. 若希望在匹配时搜索的范围局限于那些TODO关键字为未完成状态的事项,则使用C-c a M或者在搜索表达式的搜索TODO部分以`!`开头(这样可以提高搜索的速度). 例如

  • `work/WAITING` 与`work+TODO=”WAITING”`一个效果
  • `work/!-WAITING-NEXT` 搜索tag包含:work:,且TODO状态不为`WAITING`或`NEXT`的事项
  • `work/!+WAITING|+NEXT` 搜索tag包含:work:,且TODO状态为`WAITNG`或`NEXT`的事项

Timeline :对单个文件按时间排序事项

timeline会收集某个Org文件中所有的带有时间戳的事项,并用time-sorted视图显示出来. 该命令的主要目的是提供某个项目的概览.

  • C-c a L (org-timeline) 在time-sorted视图中显示某Org文件中所有带有时间戳的事项. 若调用该命令时带了C-u前缀,则还会列出截止到当天还未完成的事项(不管该事项是否带有时间戳)

    timeline buffer中可用的命令,参见Agenda commands

search view :按text查询事项

该视图只是对Org mode下的各事项进行文字匹配查询. 在查找笔记时特别有用.

  • C-c a s (org-search-view)

该命令使你可用使用布尔逻辑运算符来匹配子字符串或整个单词的事项

例如搜索”computer equipment”会查找出子串包含`computer equipment`的事项. 另外它也匹配两个单词之间由多个空格或换行符分隔的字符串(??). 搜索时还可以使用逻辑运算符,例如`+computer +wifi -ethernet -{8.11[bg]}`会搜索那些包含computer和wifi,但是不含`ethernet`也不匹配正则表达式`8.11[bg]`的事项. 这里第一个`+`是必须的,它表示开启单词搜索模式(不能只是子串匹配),其他的`+`是可选的. 详见请看命令`org-search-view`的docstring

该命令也会搜索列在`org-agenda-text-search-extra-files`中的agenda file

stuck projects :搜索哪些你需要检查的项目

若你遵从类似David Allen的GTD这样的时间管理系统来组织你的工作,你应该知道有一项工作就是定期的回顾以确定所有的项目都在推进中. 所谓stuck project是指得那种没有定义下一步行动的project. 在作回顾时,你需要找到这些project并为它们制定下一步的行动

  • C-c a # (org-agenda-list-stuck-project)

    列出所有的stuck project

  • C-c a !

    自定义变量`org-stuck-projects`,该变量决定了什么是stuck project和如何寻找stuck project

    基本上你肯定会对该变量进行配置,以适应你的实际情况. 默认的值假设你的project处于第二级的headline,并且若该project拥有`TODO`,`NEXT`,`NEXTACTION`其中一种的TODO状态时,就不是stuck的.

    假设你定义带有`PROJECT` tag的事项为project, 然后你不考虑TODO关键字为MAYBE的事项. 再进一步,假设TODO状态为DONE表示project为已完结,NEXT和TODO表明该事项为project的下一步行动. 带标签@SHOP的事项即使没有NEXT标签也认为是下一步行动. 最后假设包含`IGNORE`的project也排除在考虑范围之外. 在这种假设条件下,可用使用`+PROJECT/-MAYBE-DONE`来选择符合条件的事项为project. 然后根据project的子树是否包含TODO,NEXT,@SHOP和IGNORE的事项来决定该project是否为stuck的. 正确的配置为:

    (setq org-stuck-projects
          '("+PROJECT/-MAYBE-DONE" ("NEXT" "TODO") ("@SHOP")
            "\\<IGNORE\\>"))
        

    需要注意一点,一个project是非stuck的,Org还会去搜索它的子project是否为stuck的.

Presentation and sorting :事物在agenda中显示的方式

agenda view在显示事项前,Org mode会预先准备好要显示的事项,并对这些事项进行排序. 每个事项占据一行的位置. 每一行都以一个prefix信息开始,prefix信息中包含了该事项的分类信息以及其他重要信息(通过配置`org-agenda-tags-column`可以修改tag在那一列显示,修改`org-agenda-prefix-format`可以配置prefix信息内容).

Categories: 不是所有的任务都是等价的

agenda显示事项时可以給每个事项分配一个分类标签. 默认情况下,该分类标签的值为事项所属的Org文件名称. 但是你也可以通过在buffer中使用特殊行来指定该分类. 像这样:

#+CATEGORY: Thesis 

若你要为某个事项或子树分配特定的分类,则需要使用`:CATEGORY:`属性.

一般来说,CATEGORY的值不要超过10个字符,这样在agenda中显示时比较好看

通过定义变量`org-agenda-category-icon-alist`可以为不同的category分配不同的图标.

Time-of-day specifications: agenda是如何识别时间的

Org mode会检查每个agenda事项中的时间(time-of-day)说明. 这里的时间可以是显示在agenda中时间戳的一部分,像`< 2005-05-10Tue 19:00>`中的一部分. 时间段则由两个时间戳表示,例如`< 2005-05-10 Tue 20:30>–< 2005-05-10 Tue 22:15>`.

在事项的headline中也可以以纯文本的方式表示时间/时间段(例如`12:45`或`8:30-1pm`). 如果agenda与Emacs diary整合起来了(参见Weekly/daily agenda),diary事项中指定的时间也会被识别出来.

在显示agenda时,Org mode会将事项中抽取出来的时间转换成标准的24小时格式并作为prefix的一部分显示出来. 下面是一个例子:

8:30-13:00 Arthur Dent lies in front of the bulldozer 12:45...... Ford Prefect arrives and takes Arthur to the pub 19:00...... The Vogon reads his poem 20:30-22:15 Marvin escorts the Hitchhikers to the bridge

若agenda处于single-day mode, 或只显示当天的事项时,按时间排序的事项被嵌入到时间格中,类似下面这样

8:00...... ------------------ 8:30-13:00 Arthur Dent lies in front of the bulldozer 10:00...... ------------------ 12:00...... ------------------ 12:45...... Ford Prefect arrives and takes Arthur to the pub 14:00...... ------------------ 16:00...... ------------------ 18:00...... ------------------ 19:00...... The Vogon reads his poem 20:00...... ------------------ 20:30-22:15 Marvin escorts the Hitchhikers to the bridge

时间格的开关由变量`org-agenda-use-time-grid`决定,它的样式由变量`org-agenda-time-grid`决定

Sorting agenda item: 事项的展示顺序

在显示到view前,Org mode会对各agenda事项进行排序,排序的规则依agenda view的种类不同而不同.

  • daily/weekly agenda

    每天的事项都会被排序. 默认的顺序是,先搜集所有包含明确时间的事项. 这些事项会作为计划显示在列表的最开头部分. 然后事项依据category分组,各分组之间按照变量`org-agenda-files`的顺序排列. 各分组内部按照优先级(参见Priorities)和超过schedued/deadline的程度来排序.

  • TODO list

    事项按照各category的分类进行排序,在每个分类内部,按照优先级排序(参见Priorities). 用于排序的优先级继承至priority cookie(什么意思??),此外他还跟事项到期天数有关

  • tag matches

    事项根本不排序,只是按照找到的顺序列出而已.

配置变量`org-agenda-sorting-strategy`可以更改排序的方法

Filtering/limiting agenda items: 动态缩减agenda的展示内容

Agenda commands :远程编辑原Org tree

Custom agenda views :自定义搜索规则和显示方法

Exporting Agenda Views :导出视图到文件中

Agenda column view :使用column视图显示agenda中的事物

Publishing

org-mode还允许将一系列项目内相关的org文件发布为一系列的HTML文件,并且可以自动上传这些HTML及相关附件(例如图片,源代码文件等)到web服务器上.

配置

配置发布时,主要配置的就是 org-publish-project-alist 这个变量. 每个元素配置一个project的内容,且可能为以下两种格式中的一种

("project-name" :property value :property value ...)
;; i.e., a well-formed property list with alternating keys and values
;; or
("project-name" :components ("sub-project-name" "sub-project-name" ...))

其中,第二种格式表明”project-name”是由”sub-project-name”组成的,当publish “project-name”时,会逐个publish各个”sub-project-name”

Sources and destinations for files

这些属性指定了要发布哪些org文件,发布到哪个地方去.

:base-directory
包含源org文件的目录
:publishing-directory
发布后的产出文件存放的目录,支持通过tramp直接发布到远程主机上
:preparation-functiion
在真正发布之前被调用的函数/函数列表. 在这些函数内,可以使用变量 project-plist 来引用project property list
:completion-function
在发布动作完成之后被调用的函数/函数列表. 在这些函数内,可以使用变量 project-plist 来引用project property list

selecting files

默认情况下, :base-directory 中的所有以 .org 结尾的文件都被认为是项目的源文件. 但可以通过以下属性修改:

:base-extension
该变量可以为一个正则表达式表示以哪些后缀的源文件(不包含.)被认为是项目的源文件. 若值为符号’any,则表示 :base-directory 中的所有文件(甚至哪些无后缀的文件)
:exclude
匹配该正则表达式的文件不会被发布
:include
这时一个文件的列表,表示无论 :base-extension:exclude 怎么设置,这些文件都会被发布
:recursive
表示是否递归发布 :base-directory 中的子目录下的文件

Publishing action

发布的过程通常分为两个步骤, 第一步先将org文件转换为目标格式的文件,第二步将转换后的文件拷贝到目的目录中.

默认,会使用 org-html-publish-to-html 导出为html文件.

但是你也可以通过配置 :publishing-function 的值来设置将org文件导出为其他格式的文件.

org-latex-publish-to-pdf
导出为pdf
org-org-publish-to-org
导出为org,但是会把已归档的,已注释的以及tag-excluded的树給删掉
org-publish-attachment
并不会对文件作什么转换,因为对于类似图片这种附件来说,发布过程只需要直接拷贝到目标目录就行了

:publishing-function 的值为一个函数的list,则其中的函数会被依次调用. 且该函数应该接受三个参数:

  1. 一个至少包含 :publishing-directory 的属性列表
  2. 待发布的文件名称
  3. 输出文件存储的目录路径

这些函数要实现的功能为: 转换指定的文件并将结果文件放到目标目录下.

:htmlized-source 的值决定了发布时,是否对代码块中的代码进行作色

其他影响export的属性

下面列出其他会影响export的属性,这些属性的默认值与org的特定变量有关

export的属性org buffer对应变量
‘:archived-trees’‘org-export-with-archived-trees’
‘:exclude-tags’‘org-export-exclude-tags’
‘:headline-levels’‘org-export-headline-levels’
‘:language’‘org-export-default-language’
‘:preserve-breaks’‘org-export-preserve-breaks’
‘:section-numbers’‘org-export-with-section-numbers’
‘:select-tags’‘org-export-select-tags’
‘:with-author’‘org-export-with-author’
‘:with-creator’‘org-export-with-creator’
‘:with-drawers’‘org-export-with-drawers’
‘:with-email’‘org-export-with-email’
‘:with-emphasize’‘org-export-with-emphasize’
‘:with-fixed-width’‘org-export-with-fixed-width’
‘:with-footnotes’‘org-export-with-footnotes’
‘:with-latex’‘org-export-with-latex’
‘:with-planning’‘org-export-with-planning’
‘:with-priority’‘org-export-with-priority’
‘:with-special-strings’‘org-export-with-special-strings’
‘:with-sub-superscript’‘org-export-with-sub-superscripts’
‘:with-tables’‘org-export-with-tables’
‘:with-tags’‘org-export-with-tags’
‘:with-tasks’‘org-export-with-tasks’
‘:with-timestamps’‘org-export-with-timestamps’
‘:with-toc’‘org-export-with-toc’
‘:with-todo-keywords’‘org-export-with-todo-keywords’
‘:html-doctype’‘org-html-doctype’
‘:html-container’‘org-html-container-element’
‘:html-html5-fancy’‘org-html-html5-fancy’
‘:html-xml-declaration’‘org-html-xml-declaration’
‘:html-link-up’‘org-html-link-up’
‘:html-link-home’‘org-html-link-home’
‘:html-link-org-as-html’‘org-html-link-org-files-as-html’
‘:html-link-use-abs-url’‘org-html-link-use-abs-url’
‘:html-head’‘org-html-head’
‘:html-head-extra’‘org-html-head-extra’
‘:html-inline-images’‘org-html-inline-images’
‘:html-extension’‘org-html-extension’
‘:html-preamble’‘org-html-preamble’
‘:html-postamble’‘org-html-postamble’
‘:html-table-attributes’‘org-html-table-default-attributes’
‘:html-table-row-tags’‘org-html-table-row-tags’
‘:html-head-include-default-style’‘org-html-head-include-default-style’
‘:html-head-include-scripts’‘org-html-head-include-scripts’

写在org 文件中的option的优先级 > org-publish-project-alist 中配置的优先级 > org相关变量的值

Links between published files

在org文件中可以使用下面两种方式创建连接到另一个org文件中的链接.

[[file:foo.org][The foo]] 
file:foo.org

当发布这种org文件时,这种连接到org的链接会自动转换为连接到对应的html文件.

若你不希望进行这种转换,则需要使用 http: 协议而不能是 file: 协议.

Generating a sitemap

:auto-sitemap
若为非nil,则在 `org-publish-current-project’ 或 `prg-publish-all’ 时自动发布sitemap
:sitemap-filename
sitemap的输出文件名,默认为`sitemap.org’(发布后变成sitemap.html)
sitemap-title
sitemap网页的title. 默认为sitemap的文件名
sitemap-function
用来生成sitemap的函数. 默认为 org-publish-org-sitemap,它会生成一个系列连接到项目内其他文件的链接列表
sitemap-sort-folders
sitemap中文件夹的存放位置. 默认是 first,表示将文件夹放在最前面. 也可以设置成 last,表示将文件夹放在最后面. 其他的值则表示交叉放置
sitemap-sort-files
sitemap中文件的排序方式. 默认为 alphabetically,还可以是 chronologicallyanti-chronologically
sitemap-ignore-case
sitemap中文件排序时,是否忽略大小写,默认为nil表示不忽略
sitemap-file-entry-format
指定sitemap中链接的格式. 其中 %t 表示title, %a 表示author, %d 表示date,该date由函数 org-publish-find-date 获取,并经由 org-publish-sitemap-date-format 格式化
:sitemap-date-format
指定了sitemap entry中的date的显示格式
:sitemap-sans-extension
若为非nil,则在产生sitemap时会删除掉文件名的后缀. 默认为nil

Generating an index

org-mode发布时,可以自动产生index文件.

:makeindex
若为非nil,则会产生 theindex.org 并发布为 theindex.html

The file will be created when first publishing a project with the :makeindex set. The file only contains a statement #+INCLUDE: theindex.inc. You can then build around this include statement by adding a title, style information, etc.

发布相关命令

C-c C-e P x (org-publish)
选择并发布项目
C-c C-e P p (org-publish-current-project)
发布当前文件所属的项目
C-c C-e P f (org-publish-current-file)
只发布当前文件
C-c C-e P a (org-publish-all)
发布所有项目

org根据时间戳来决定文件是否被修改. 一般情况下,上面的函数只会发布已经更改过的文件. 但可以通过以下几种方法来强制发布所有文件

  • 调用上面函数时,带上前缀参数
  • 设置变量 org-publish-use-timestamps-flag 为nil

例子

一个单组件项目的发布

下面的例子中,将一些org文件发布到本机的 ~/public_html 目录中

(setq org-publish-project-alist
         '(("org"
            :base-directory "~/org/"
            :publishing-directory "~/public_html"
            :section-numbers nil
            :with-toc nil
            :html-head "<link rel=\"stylesheet\"
                       href=\"../other/mystyle.css\"
                       type=\"text/css\"/>")))

一个多组件项目的发布

下面是一个复杂的多的项目发布例子. 除了将org文件发布成html文件外,还包括图片,源代码和样式文件的发布.

(setq org-publish-project-alist
      '(("orgfiles"
          :base-directory "~/org/"
          :base-extension "org"
          :publishing-directory "/ssh:user@host:~/html/notebook/"
          :publishing-function org-html-publish-to-html
          :exclude "PrivatePage.org"   ;; regexp
          :headline-levels 3
          :section-numbers nil
          :with-toc nil
          :html-head "<link rel=\"stylesheet\"
                  href=\"../other/mystyle.css\" type=\"text/css\"/>"
          :html-preamble t)

         ("images"
          :base-directory "~/images/"
          :base-extension "jpg\\|gif\\|png"
          :publishing-directory "/ssh:user@host:~/html/images/"
          :publishing-function org-publish-attachment)

         ("other"
          :base-directory "~/other/"
          :base-extension "css\\|el"
          :publishing-directory "/ssh:user@host:~/html/other/"
          :publishing-function org-publish-attachment)
         ("website" :components ("orgfiles" "images" "other"))))

Working with source code

org提供了对代码块的多种处理方式,比如使用原生的major-mode编辑代码块,执行代码块,将代码块抽取到其他源文件中去,导出代码块及其结果为其他格式的文档.

代码块的结构

代码块的结果一般如下所示:

#+NAME: <name>
#+BEGIN_SRC <language> <switches> <header arguments>
       <body>
#+END_SRC

还有一种简写形式如下:

src_<language>{<body>}

src_<language>[<header arguments>]{<body>}

其中

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

编辑代码块

使用 C-c ' 来编辑当前的代码块. 它会新开一个编辑buffer,进入<language>的major mode,并插入代码块的原内容. 在该编辑buffer中按 C-x C-s 会将编辑buffer中的内容写回原代码块. 当然,你可以通过设置 org-edit-src-auto-save-idle-delay 的值来设置空闲多少秒后自动保存buffer内容. 或者通过设置 org-edit-src-turn-on-auto-save 来让进入代码块后自动开启 auto-save-mode 若编辑完后,想退出编辑窗口,再按一次 C-c ' 即可.

在按 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控制了导出代码块及其执行结果时的行为.

  • :exports code

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

  • :exports results

    执行代码块并导出结果. 若之前已经有了该代码块的结果,则更新之前的结果而不是插入新的结果.

    代码块本身不会被导出

  • :exports both

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

  • :exports none

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

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

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

抽取代码块

从代码块中抽取代码存到一个纯源代码文件中的过程称之为”tangling”(这一术语来源于文学编程社区). 在tangling的过程中,代码块中的代码会经过 org-babel-expand-src-block 的扩展,该函数会扩展代码块中的变量与 noweb 风格的引用.

Header arguments

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

Function

org-babel-tangle
tangle当前文件,若带有prefix argument则只tangle当前代码块. 快捷键为 C-c C-v t
org-babel-tangle-file
选择一个文件来tangle. 快捷键为 C-c C-v f
org-babel-tangle-jump-to-org
该函数可以从tangle的代码处跳回源org文件的代码块处. 但前提是 padline header argument必须为True(默认),且 comment header argument必须为 link

Hooks

org-babel-post-tangle-hook
Hook run in code files tangled by `org-babel-tangle’.

执行代码块

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

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

最简单的执行代码块的办法就是把光标定位到代码块中,然后按下 C-c C-c 或者 C-c C-v e, 这会调用 org-babel-execute-src-block 函数来执行代码块并将结果插入org buffer中.

若为代码块命名了,则可以在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

支持的语言

Python

C / C++

Lisp

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为代码块中最后一个语句的返回值
    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到源代码文件中

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_SRC python :results output :session
 print "hello"
 2
 print "bye"
#+END_SRC

#+RESULTS:
: hello
: 2
: bye

Noweb引用语法–org mode下的文学编程

noweb 文学编程系统允许使用类似 <<code-block-name>> 的格式来引用一段命名的代码块.

当代码块被tangled或执行时,是否将noweb引用扩展为对应代码的行为由代码块的 :noweb 决定. :noweb yes 表示代码块执行前,其中的noweb引用会被扩展. 默认值为 :noweb no 表示不会扩展.

也可以引用命名代码块的执行结果而不是代码内容. 语法是 <<code-block-name(optional arguments)>>

若org文件特别大,则noweb tangle起来会很缓慢,则考虑设置 ~org-babel-use-quick-and-dirty-noweb-expansion~ 为t,但代价是无法正确识别继承的 ~:noweb-ref~ 参数

代码块相关快捷键与函数

在代码块中

‘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-babel-tangle

#!/bin/sh
# -*- mode: shell-script -*-
#
# tangle files with org-mode
#
DIR=`pwd`
FILES=""

# wrap each argument in the code required to call tangle on it
for i in $@; do
    FILES="$FILES \"$i\""
done

emacs -Q --batch \
      --eval "(progn
     (add-to-list 'load-path (expand-file-name \"~/src/org/lisp/\"))
     (add-to-list 'load-path (expand-file-name \"~/src/org/contrib/lisp/\" t))
     (require 'org)(require 'org-exp)(require 'ob)(require 'ob-tangle)
     (mapc (lambda (file)
            (find-file (expand-file-name file \"$DIR\"))
            (org-babel-tangle)
            (kill-buffer)) '($FILES)))" 2>&1 |grep tangled

Footnotes

[fn:1] install-info的输出也是系统依赖的. 在特定的Debian及其衍生系统中使用两种不同版本的install-info程序.如果你看到

This is not dpkg install-info anymore, but GNU install-info
See the man page for ginstall-info for command line arguments  

只管忽略它就好.

[fn:2] 如果你不想在全局范围使用font-lock,你可以用下面一句配置来只在Org-mode下打开font-lock选项

(add-hook 'org-mode-hook 'turn-on-font-lock) 

[fn:3] 请考虑订阅邮件列表,以减少工作邮件列表版主的工作量。

[fn:4] 要配置C-a,C-e和标题环境中C-k的行为,参见参数’org-special-ctrl-a/e’, ‘org-special-ctrl-k和’org-ctrl-k-protect-subtree’

[fn:5] 参见org-cycle-emulate-tab选项

[fn:6] 参见org-cycle-global-at-bob选项

[fn:7] indirect buffer(关于indirect buffer的更多信息请查看Emacs手册)仅仅包含了原buffer中当前树的内容. 编辑这个indirect buffer也会修改原buffer,但是对原buffer的可见性不会有影响

[fn:8] 如果你不想一行内容被分割,你需要定制变量’org-M-RET-may-split-line’

[fn:9] 参见变量’org-show-hierarchy-above’,’org-show-following-heading’,’org-show-siblings’和’org-show-entry-below’,这些参数详细定义了每次匹配多少内容

[fn:10] 这种行为依赖于’org-remove-highlights-with-change’选项

[fn:11] 这种方法在Xemacs中是行不通的,because XEmacs uses selective display for outlining, not text properties.

[fn:12] 当使用*作为列表项的标志时,这一行必须是有缩进的,否则它们会被认为是顶层的标题. 同样的道理,如果你为了得到一个干净的大纲视图而隐藏了前面的星星,那么以*开头的列表项和真正的标题之间会很难区分. 总之,即使支持’*’作为列表项标志,但最好还是不要用它.

[fn:13] 你可以通过配置’org-plain-list-ordered-item-terminator’来过滤掉它们中的任何一个.

[fn:14] 通过配置’org-alphabetical-lists’,你也可以用类似’a.’,’A.’,’a)’,’A)’作为列表项的标志. 为了最小化与普通文档的混淆,只准使用单个字符作为标志. 超过这个限制,列表项标志会自动变回数字.

[fn:15] 如果列表项中包含有复选框,那么这种标志必须放在复选框的前面. 如果你激活了字母列表,你也可以使用类似[@b]这样的形式.

[fn:16] 参见’org-empty-line-terminates-plain-lists’

[fn:17] Org只会改变Emacs的filling设置,对于XEmacs,你应该是i用Kyle E.Jones的’filladapt.el’.为了启用这个包,在’.emacs’中添加’(require ‘filladapt)’

[fn:18] 如果你不想分割列表项,自定义变量’org-M-RET-may-split-line’

[fn:19] 如果你想用这种方式遍历列表项,你可能需要自定义’org-list-use-circular-motion’

[fn:20] 循环行为参见’org-liste-use-circular-motion’

[fn:21] 欲了解列表项标志的更多规则,参见’org-list-automatic-rules’

[fn:22] 你可以在每个文件中定义drawers,方法为添加一行类似’#DRAWERS: HIDDEN PROPERTIES STATE’这样的一行.

[fn:23] 相应的in-buffer设置为: ‘#+STARTUP: fninline’或者’#+STARTUP nofninline’

[fn:24] 相应的in-buffer设置为: ‘fnadjust’ 和 ‘nofnadjust’.

[fn:25] 要插入一个竖线到表格域中,使用\ vert(去掉空格)代替,若要插入竖线到单词中,则用\ vert{}(去掉空格)代替,例如abc|def.

[fn:26] 这个特征在XEmacs上无效

[fn:27] 诚然它在Emacs中是无效的,但是它在导出为HTML使却有效.

[fn:28] Org能够识别用户使用’B4’这种写法,但是当Org提供公式来编辑时,不会采用这种引用的表示法. 你可以使用变量’org-table-use-stand-references’来定制这种行为.

[fn:29] 为了向后兼容性,你可以使用特定的名称类似$LR5和$LR12,分别引用的是表格的倒数第5和倒数第12行. 然而,现在这种语法已经被弃用, 在新文档中不应该再使用这种语法了,现在使用@>$代替.

[fn:30] 这种操作所花时间的时间复杂度为O(N^2),因为表格FOO需要首先被解析一边这样每一行才能被拷贝过来.

[fn:31] ‘constants.el’通过两种单位系统来提供常量值,分别是SI和cgs. 具体使用哪个单位系统取决于变量’constants-unit-system’的设置. 你也可以通过#+STARTUP选项中的constSI和constcgs来为某个文件设置该属性的值.

[fn:32] 使用printf进行重新格式化时,精度的指定是收到限制的.这是因为,传给printf的值会自动被转换为integer或double类型. integer型数字被限制为包括符号位一共32bit,超过就会被截断. 而double型被限制为精度为64位其中保留16位小数(leaves approximately 16 significant decimal digits)

[fn:33] 这里名字必须是以字母数字开头,并且只使用字母数字和下划线

[fn:34] 注意:在第一个标题前的文本通常是不会导出的,因此第一个这种链接吊臂应该是在第一个标题之后的,或者在第一个标题前但是与第一个标题是同一行的位置.

[fn:35] 当要插入一个连接到标题的链接时,可以使用in-buffer补完功能. 只需要输入一个星号(*)随后跟着几个可选的字母,然后按下M-<TAB>, 当前buffer中所有的标题都会作为补完的选项显示出来.

[fn:36] 搜索的实际行为依赖于变量’org-link-search-must-match-exact-headline’的值. 如果该值为nil则执行模糊查询. 如果该值为t,则精确匹配标题. 如果该值为’query-to-create’则精确匹配标题,但若匹配不到,则创建一个新标题.

[fn:37] 如果标题中含有时间戳,时间戳部分不会包含在链接中,从而导致一个错误的链接,因此,最好不要在标题中放置时间戳

[fn:38] 你不是一定要用这个命令才能插入链接. Org中的链接其实只是个纯文本而已, 你可以直接在buffer中输入或者复制这些文本. 使用这个命令,链接自动被双方括号括住,随后你需要输入可选的描述信息

[fn:39] 把存储的链接插入buffer之后,这个链接会从存储链接的列表中移走. 如果你希望插入链接之后,链接还保存在列表中,你可以使用`c-u c-u c-u c-c c-l`或者配置选项`org-keep-stored-link-after-insertion`

[fn:40] 这是通过`org-PREFIX-complete-link`这个函数来实现的

[fn:41] 参见变量`org-display-internal-link-with-indirect-buffer`

[fn:42] 对应#+STARTUP中的关键字`inlineimages`

[fn:43] 为了向后兼容,当附加信息为行号时,也可以使用单冒号(:)

[fn:44] 当然,你可以创建一个只包含TODO事项列表的文档,但这并不是必须的

[fn:45] 改变这个变量之后,需要重启Org mode才能生效

[fn:46] 这一点对于timeline和agenda缓存区中的t命令也适合

[fn:47] 如果你不想区分tag和todo状态的话,通过配置变量`org-fast-tag-selection-include-todo`可以让你在改变tag的时候自动改变TODO状态(参见章节设置tag).注意,这意味着你需要为两组关键字分配相同的快捷键

[fn:48] Org-mode只在读入文件的时候才会去解析这些配置行. 在以`#+`开头的行按下`C-c C-c`的作用是为当前buffer重启一次Org-mode

[fn:49] 对应的文件内设置是#+STARTUP: logdone

[fn:50] 对应的文件内设置是#+STARTUP: lognotedone

[fn:51] 参见变量`org-log-states-order-reversed`

[fn:52] 当你设置了STARTUP参数`org-log-done`,同时又为状态设置了记录动作的时候,就有可能出现连续记录了两次时间戳的情况. 然而,即使你两边都配置了记录附加信息的动作,org也不会提示你输入两次附加信息.为状态单独设置的记录动作会优先执行.

[fn:53] 另见选项`org-priority-start-cycle-with-default`

[fn:54] 如果你希望全局的TODO列表中不现实子任务,参见`org-agenda-todo-list-sublevels`

[fn:55] 默认不包括描述列表在内. 但是通过修改`org-list-automatic-rules`你也可以允许描述列表成为checkbox

[fn:56] 如果你希望统计的时候统计所有层次的下级checkbox而不仅仅是直接子checkbox,那你需要修改变量`org-hierarchical-checkbox-statistics`

[fn:57] 如果在列表的第一行使用`C-u C-c C-c`,而刚好这一行事项没有checkbox标识. 则会给该列表所有事项都加上checkbox的标识

[fn:58] 就跟其他文件内设置一样,按`C-c C-c`使这行设置生效

[fn:59] 只有在搜索不涉及到包括属性在内的复杂匹配模式的情况下才成立

[fn:60] 如果tag没有明确配置快捷键,那么org会自动給它们分配快捷键

[fn:61] 注意,在定义COLUMN格式时,必须写在同一行中

[fn:62] 也就是说它不属于Emacs内置的一部分(访问http://orgmode.org)

[fn:63] 当你手工输入时间戳时,星期不是必须的. 但若你是用Org命令来修改或插入时间戳,则会自动插入星期,这样更方便一些

[fn:64] 这里准照的是ISO8601日期/时间规范. 若要采用其他规范,参见定制时间规范

[fn:65] 当使用这种diary风格的类lisp表达式时,你需要非常小心检查这些参数的调用顺序. 这种顺序严重依赖于变量`calendar-date-style`(对旧版本的Emacs来说是`european-calendar-style`). 例如要指定日期`2005年12月12日`,根据不同的设置分别可以用`(diary-date 12 1 2005)`,`(diary-date 1 12 2005)`,`(diary-date 2005 12 1)`来表示. 这常常让人很疑惑. 用户可以求助于某些特定函数,例如`org-date`或`org-anniversary`. 这些函数跟那些以`diary-`打头的diary函数功能上差不多,但他们的参数使用的是固定的ISO顺序(年,月,日的顺序)而与`calendar-date-style`的值无关

[fn:66] 参见变量`org-read-date-prefer-future`. 你可以通过设置该值为符号`time`(也就是`’time`),这样之后可以让Org-mode当前时间之前的时间说明当成是明天的时间.

[fn:67] 如果你不想要calendar出现,配置变量`org-popup-calendar-for-date-prompt`

[fn:68] 如果你觉得这会让你分心,通过配置`org-read-date-display-live`来打开/关闭这种显示

[fn:69] 它会一直显示,即使本标记为完成状态还是会显示. 如果你不想这样,设置变量`org-agenda-skip-scheduled-if-done`

[fn:70] 最后期限和规划日期放置的为止需要紧跟在表示任务的标题行之下. 不要在中间插入任何其他内容.

[fn:71] 相对应的#+STARTUP关键字有logredeadline, lognoteredeadline, 和 nologredeadline

[fn:72] 相对应的#+STARTUP关键字有logreschedule, lognotereschedule, 和 nologreschedule

[fn:73] 事实上任务变回的目标状态由一下流程决定:先取属性`REPEAT_TO_STATE`的值,然后取变量` org-todo-repeat-to-state`的值,若都取不到,则默认为TODO状态序列的第一个状态

[fn:74] 你可以通过更改变量`org-log-repeat`的值来更改这种行为模式,或者设置#+STARTUP选项为logrepeat,lognoterepeat和nologrepeat中的其中一个. 若设置为lognoterepeat,则你会被提示输入记录内容.

[fn:75] 若希望Emacs假设你在这段时间内依然是在做这项任务,使用配置(setq org-clock-persist t)

[fn:76] 要实现自动进行工作量评估,为`org-clock-in-prepare-hook`增加hook函数来实现工作量评估

[fn:77] 该时间同时由属性`LAST_REPEAT`持有

[fn:78] 参见变量`org-clock-modeline-total`

[fn:79] 对应的单文件设置为` #+STARTUP: lognoteclock-out `

[fn:80] 可以通过变量`org-clock-clocktable-language-setup`来设置language item

[fn:81] 需要注意的是,所有的参数必须写在同一行,这里之所以分行只是为了好看

[fn:82] 对于安装Mac OS X的计算机,所谓的空闲时间指的是用户未操作电脑的时间而不仅仅是不操作Emacs的时间. 对于X11的系统,你可以安装一个辅助程序`x11idle.c`来实现这样的功能,该程序可以在org git分发包的UTILITIES目录下找到. 对于其他系统,空闲时间只是指的没有操作Emacs的时间

[fn:83] 可以通过变量`org-effort-property`来改变属性的值

[fn:84] Please note the pitfalls of summing hierarchical data in a flat list (参见章节 Using column view in the agenda)

[fn:85] 这里C-c c可以换成你想要的任何键序列

[fn:86] 使用\%来输入%

[fn:87] 若你自定义自己的link type(参见 Adding hyperlink types).

[fn:88] This will always be the other, not the user. See the variable org-from-is-user-regexp.