0%

程序员对于“TODO”这个词一定不陌生。一个TODO意味着有一件事情需要去做。更深入一步来说,TODO是一个未完成的任务。

Org-mode能够完美解决任务管理的各种问题,包括任务/子任务的划分,关键时间的设定,任务状态变化的跟踪,以及任务的检索和查询。
再配合
Org-mode的强大编辑功能
能够实现很多功能,比如时间管理(GTD),项目计划和管理,工作日志等。

本文介绍Org-mode强大的任务管理功能。

定义任务和子任务

Org-mode认为,每一个任务通常会需要附带一些文字说明。所以Org-mode将标题作为任务的载体。通过在标题上增加状态标记,来定义任务。
由于大纲是分级的,所以将标题定义为任务天然支持了子任务:可以在子标题上标记子任务。

使用 C-c C-t 或者 S-LEFT/RIGTH 可以为标题增加或改变任务标记。

定义任务状态

Org-mode内置的任务状态只有两种:TODO和DONE。如果需要更多的状态,需要自己定义。

可以在文件内部定义任务状态: 关键字应该各不相同,这样对于一个选项 Org
才知道该用哪个状态序列(集合)。
例子中也给出了快速使用一个关键字的方法,就是在关键字后面括号中给出快捷字母
。当用 C-c C-t 时,会询问,让你输入一个字母。

要自定义任务状态,可以使用文档元数据 #+SEQ_TODO
,可以在文档的任何地方定义,但是建议统一定义在文档头部:

1
2
#+SEQ_TODO: REPORT(r) BUG(b) KNOWNCAUSE(k) | FIXED(f)
#+SEQ_TODO: TODO(T!) | DONE(D@)3 CANCELED(C@/!)

将光标放在这些内容上,输入 C-c C-c 可以直接生效。此时再用 C-c C-t
设定任务时,会打开一个新的缓冲区:

对照前面的定义不难发现:

  • 可以定义多组状态序列,每个 #+SEQ_TODO 行定义一组
  • 状态之间用空格分隔
  • 可以在()中定义附加选项,包括:
    • 字符:该状态的快捷键
    • !:切换到该状态时会自动增加时间戳
    • @ :切换到该状态时要求输入文字说明
    • 如果同时设定@和!,使用 @/!
  • |
    分隔未完成状态和已完成状态。未完成状态在查询待办事项时会列出。

使用C-c C-t 或者 S-LEFT/RIGTH 切换一些状态后,任务会变成这个样子:

会自动生成时间戳,提示填写说明。从而留下完整的记录。

上面的任务状态设置只适用于当前文档。如果希望设定所有 .org
文档的默认任务状态,需要在 .emacs 配置文件中定义。
上面的任务状态在配置文件中的等效设置为:

1
2
3
4
(setq org-todo-keywords
'((sequence "REPORT(r)" "BUG(b)" "KNOWNCAUSE(k)" "|" "FIXED(f)")
(sequence "TODO(T!)" "|" "DONE(D@)3" "CANCELED(C@/!)")
))

除了状态序列外,还可以定义type,来标记任务的分类。可以参考这里

设置任务优先级

在Org-mode中,还针对任务设定了A,B,C三种优先级,在安排日程的时候可以按照优先级进行排序。为任务设定优先级是通过快捷键
S-UP/DOWN

跟踪子任务完成情况

对于有多个子任务的上级任务,很常见的一个需求是随时跟踪子任务的完成情况。
Org-mode支持在上级任务上增加标记,当子任务的状态发生改变时自动更新上级任务的完成情况。
支持百分比和分数两种形式,类似 [66%] 或者 [2/3]

可以在上级任务标题中的任意位置插入 [%] 或者 [/],
当子任务的状态发生变化时,会自动更新该位置的值。 比如:

1
2
3
4
5
6
* Organize Party [%]
** Call people [/]
*** Peter
*** Sarah
** Buy food
** Talk to neighbor

注意:

  1. 当改变子任务状态时,只更新上一级任务的完成情况,不可级联。
  2. 即使所有的子任务都完成,也只是标记上一级任务的完成情况为100%,而不能自动更新上级任务的完成状态。如果需要自动设定为完成,可以在.emacs中增加如下配置:
1
2
3
4
(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"))))

:

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

用复选框标记非标题类型的子任务

前面的任务和子任务都是标题形式。Org-mode还支持非标题形式的子任务。对于以
[ ] 开头的列表
会被当作复选框。这样就形成了局部的子任务,
适用于将一个任务划分成几个简单的步骤。 下面是一个例子:

1
2
3
4
5
6
7
8
*** 一个任务 [0/2]
该任务包含几个步骤:
- [-] 步骤1 [1/2]
- [X] 步骤1.1
- [ ] 步骤1.2
- [-] 步骤2 [1/2]
- [X] 步骤2.1
- [ ] 步骤2.2

与子任务类似,步骤的状态变化会改变上级步骤/任务的完成情况。
下面是复选框相关的命令:

KEYS COMMENT


C-c C-c 改变复选框状态
M-S-RET 增加一个子项

查询任务

Org-mode的编辑功能
中介绍过大纲的检索功能:

1
C-c /     只列出包含搜索结果的大纲,并高亮,支持多种搜索方式

该功能可以按照多种方式检索,其中针对任务有两种方式:todo 和 TODO key
words,分别实现高亮所有TODO和具有特定关键字的TODO。

任务的时间计划

Org-mode中的任务还可以设置计划时间(SCHEDULED)和截止时间(DEADLINE),方便任务的管理和排程。

时间戳

在Org-mode中,将带有日期和时间信息的特定格式的字符串称为时间戳。时间戳使用”<
>“进行标记,比如:

1
2
3
<2005-10-01 Tue>
<2003-09-16 Tue 09:39>
<2003-09-16 Tue 12:00-12:30>

时间戳分为两种,上面的例子中的时间戳都标记了一个”时间点“,另外一种时间戳标记重复出现的多个时间点。
使用时间点+ 间隔( 天(d)、周(w)、月(m)或者年(y))来表示。比如:

1
<2007-05-16 Wed 12:30 +1w>

表示从2007-05-16 12:30开始,每周重复一次。

时间戳可以放在标题或正文的任何部分。

输入时间戳时,可以手工输入符合格式的标记,也可以使用快捷键 C-c .
来创建。

如果要快速输入日期无需选择,可以直接用 C-c <

C-c > 可以查看日历。

如果仅仅想输入一个日期/时间,与任务没有任何关系,可以用 C-c !


S-left,S-right 以天为单位调整时间戳时间
S-up,S-down 调整光标所在时间单位;如果光标在时间戳之外,调整时间戳类型(是否在日程表中显示)


时间/日期段

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

1
<2004-08-23 Mon>--<2004-08-26 Thu>

连续使用 C-c . 可以创建时间段

C-c C-y 计算时间段的间隔

计划时间和截止时间

Org-mode可以为任务设定一个计划时间(SCHEDULED), 输入 C-c C-s
,就可以设定光标所在位置所属的任务的计划时间。 而 C-c C-d
是输入截止时间(DEADLINE)。

全局任务文件清单

前面的内容都是关于单个 .org 文件的任务管理。Org-mode还支持将多个
.org 文件组合起来进行管理。这带来很多好处:

你可以按照不同的用途将任务放在不同的文件中进行组织,比如项目,个人事务,家庭等等。

要让Org-mode知道需要把哪些文件视为全局任务的组成部分,需要设定一个清单,可以在
.emacs 中这样设置:

1
2
3
4
5
(setq org-agenda-files (list "~/.todos/work.org"
"~/.todos/projects.org"
"~/.todos/home.org"
"~/Documents/todo/"
))

清单中可以加入文件或目录。如果是目录,该目录下的所有 .org
文件都会被加入清单。

除了预定义的清单文件,还可以在编辑任务文件( .org )时随时使用 C-c [
C-c ] 将文件加入/移出清单。

可以随时通过 C-c '/ , 循环打开所有的清单文件。

全局 TODO 列表

全局TODO列表列出所有全局任务文件中的未完成任务。通过快捷键 C-c a t
进入全局 TODO 列表。

在全局TODO列表中,用 t 键改变任务状态,;按 RET
跳到该条目所在的源文件。

如果提示 C-c a 快捷键未定义,是因为Org-mode的快捷键没有启用,需要在
.emacs 中增加配置:

1
2
3
4
(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)

日程表

有时候可能需要根据未完成任务显示日程安排,通过 C-c a a
可以进入日程表视图。 日程表根据任务的计划时间列出每天的任务。

在日程表视图中按 "l"(小写字母L)
显示日志。这样就会显示你所有已经完成的任务和他们完成的时间。

小结

这里涉及到的都是关于Org-mode任务管理的一些基本使用,正是这些强有力的基础,使得Org-mode可以用于时间管理(GTD)、项目计划和管理、
工作日志等各种用途。

尽管按照org-mode 官方 的说法,Org
是一个基于快速高效的文本方式来实现做笔记、管理待办事项(TODO
list)以及做项目计划的模式(Org is a mode for keeping notes, maintaining
TODO lists, and doing project planning with a fast and effective
plain-text system ),但 Org-mode 首先是最好的文档编辑利器,没有之一。

我之前用过很多年M$Word, 也尝试过OpenOffice/LibreOffice
Writer,以及iWorks
Pager,但都不理想,写文档是没有痛快淋漓的感觉。直到后来发现了Omni
Outliner
,
才终于找到了写作的乐趣。
但是了解了org-mode之后,发现原来一切都是浮云。只有Org-mode才是终极的解决之道。
使用org-mode写文档的时候,你只需要关注内容本身,而不需要写上几个字,选中它们按Ctl-B,或者停下来用鼠标去点击“标题1”,更甚觉得那个标题格式不顺眼,开始去调整样式,而停下写作的思路。

BTW,Omni Outliner似乎也是从Org-mode找到的灵感,有图为证:

OmniOutliner

其功能与Org-mode 几乎一样,而且这货居然支持emacs快捷键!

尽管Omni
Outliner以GUI的方式实现了org-mode的功能,但是并不是很理想:它的内容是“所见即所得”的,很多时候你难以更改其样式,而且只能在Mac
OS下使用。 而Org-mode使用文本方式,具有如下优势:

  • 格式通用,系统无关,软件无关
  • 体积小,速度快
  • “所想即所得”,比“所见即所得”更人性化

可以说,正是由于有了 Org-Mode, Emacs
处理文本的能力才得到了大幅度的提高,使得Emacs能够被非程序员接受。
如果说LaTex是排版的终极,那么Org-mode就是编辑的终极。Emacs 22
以后的版本已经集成了 org-mode,打开 .org 扩展的文件会自动进入 org
模式。此外,Vim下面也有了对应的Org-mode。

本文介绍最基本的编辑、格式化文本以及导出功能,后续再讨论高级玩法。

用大纲组织内容

尽管Org-mode的功能不断丰富,现在已经可以记笔记,管理个人事务,制定项目计划以及很多其他的用途,但是最初和最基本的功能还是通过大纲(outline)的方式来编辑文档。
而且,无论是笔记管理,任务管理还是项目计划的编写,都是以对内容进行高效的组织(organization)为基础的。

在编辑文档,尤其是大型文档的时候,对内容的组织就显得尤为重要。经常需要在文档中快速定位,只关注某一部分的内容,
Word之类的编辑器,通过文档结构图来定位文档位置,速度很慢,而且很多时候不能满足编辑的需要。尽管Word也提供了“大纲视图”,但是,唉……不说也罢,
如果那个功能真的好用,也就不需要Omni Outliner了。

Org-mode天然支持大纲视图,通过在文档中定义标题,可以方便的浏览每个小节,从而把握文档的总体内容。
Org是基于Outline模式的,它提供了更灵活的编辑结构文件的命令。比如折叠文档,针对大纲的编辑功能等,极其强大。

定义标题

要实现大纲,首先要定义标题。用emacs新建一个orgmode.org,输入如下内容:

1
2
3
4
5
6
* org-mode
** 大纲
正在编写大纲
** 轻量级标记语言
* 可以导出其他格式
支持html,pdf等格式

注意:

  1. * 要位于每行的行首
  2. * 之后要有一个空格,然后再输入标题
  3. 连续几个 * 就表示是第几级大纲,最多支持10级。

此时看起来应该是这个样子:

org-mode

觉得没什么出奇的地方,只是改变了一些颜色?其真正的用处在于可以通过大纲操作文档,包括折叠,定位和编辑。
而这些操作都通过快捷键实现,非常有效率。尤其是对大文档。

大纲相关的快捷键

折叠大纲

快捷键 命令 说明
S-TAB org-shifttab 循环切换整个文档的大纲状态(三种状态:折叠,打开下一级,打开全部)
TAB org-cycle 循环切换光标所在大纲的状态

在大纲之间移动

快捷键 命令 说明
C-c C-n/p 下/上一标题
C-c C-f/b 下/上一标题(仅限同级标题)
C-c C-u 跳到上一级标题
C-c C-j 切换到大纲浏览状态

基于大纲的编辑

快捷键 命令 说明
M-RET 插入一个同级标题
M-S-RET 插入一个同级TODO 标题
M-LEFT/RIGHT 将当前标题升/降级
M-S-LEFT/RIGHT 将子树升/降级
M-S-UP/DOWN 将子树上/下移
C-c * 将本行设为标题/正文
C-c C-w 将子树或区域移动到另一标题处(跨缓冲区)
C-x n s/w 只显示当前子树/返回
C-c C-x b 在新缓冲区显示当前分支(类似C-x n s)
C-c / 只列出包含搜索结果的大纲,并高亮,支持多种搜索方式
C-c C-c 取消高亮

更多的快捷键可以通过 C-c C-x C-h 查看。

大纲的显示方式

默认的大纲显示没有缩进,显得有些乱。可以用 M-x
org-indent-mode切换到另一种显示方式:

大纲缩进

如果想让某个文件默认用这种方式打开,可以在文件头部增加:

1
#+STARTUP: indent

如果希望打开所有org文件都默认用这种方式,可以在.emacs中配置:

1
(setq org-startup-indented t)

超链接和图文混排

超链接也是组织内容的一种非常有效的方式。Org
支持多种超链接。对于符合要求的图片链接,可以形成图文混排。

创建链接

对于符合链接规则的内容,org-mode会自动将其视为链接,包括括文件、网页、邮箱、新闻组、BBDB
数据库项、IRC 会话和记录等。下面是一些例子:

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

对于文件链接,可以用::后面增加定位符的方式链接到文件的特定位置。定位符可以是行号或搜索选项。如:

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

除了上述的自动链接外,还可以显示指定链接,采用如下格式:

1
2
[[link][description]]
[[link]]

显示指定的链接可以不显示原始的URL而是显示对该链接的描述。
这种方式可以用相对路径链接本地文件。

对于显示指定的链接,即可以手工输入,也可以用org-mode提供的快捷键进行编辑:

快捷键 命令 说明
C-c l 保存链接
C-c C-l org-insert-link 创建或修改链接,可以引用已保存的链接
C-c C-o org-open-at-point 打开链接
C-c % 记录内部链接地址
C-c & 跳转到已记录的内部链接

内部链接

前面的例子都是外部链接,Org-mode还支持内部链接:

1
2
定义锚点 #<<my-anchor>>
[[my-anchor][内部链接]]

脚注可以看作是一种特殊的内部链接,但是要求具有"fn:"前缀:

1
2
添加脚注链接 [[fn:footprint1][脚注1]]
定义脚注 [fn:footprint1]

显示图片

尽管不看重"所见即所得",但有时候能够看到图文混排的内容还是很有必要的。通过iimage这个minor
mode,可以在Org-mode中显示图片。 下载 iimage.el 文件扔到 Emacs
的目录里,然后在 .emacs 里添加下面的代码:

1
2
3
;; iimage mode
(autoload 'iimage-mode "iimage" "Support Inline image minor mode." t)
(autoload 'turn-on-iimage-mode "iimage" "Turn on Inline image minor mode." t)

然后就可以用命令 M-x iimage-mode RET 在当前模式里启动 iimage 这个
minor mode。

iimage-mode目前只能显示以文件方式链接的图片。

轻量级标记语言

前面的大纲和超链接都是使用标记来定义的。实际上,Org现在已经成为一种专门的轻量级标记语言,与Markdown、reStructedText、Textile、RDoc、MediaWiki等并列。

相对于重量级标记语言(如html,
xml),轻量级标记语言的语法简单,书写容易。即使不经过渲染,也可以很容易阅读。用途越来越广泛。
比如,gitHub的README文档除了支持纯文本外,还支持丰富的轻量级标记语言,其中就包括Org。

关于这些语言的对比,可以参考这里
。下面来看一下Org还支持哪些标记。

字体

1
2
3
4
5
6
7
*粗体*
/斜体/
+删除线+
_下划线_
下标: H_2 O
上标: E=mc^2
等宽字: =git= 或者 ~git~

表格

Org 能够很容易地处理 ASCII
文本表格。任何以‘|’为首个非空字符的行都会被认为是表格的一部分。’|‘也是列分隔符。一个表格是下面的样子:

1
2
3
4
| Name  | Pone | Age |
|------:|:----:|:----|
| Peter | 1234 | 17 |
| Anna | 4321 | 25 |

你可能认为要录入这样的表格很繁琐,实际上你只需要输入表头“|Name|Pone|Age”之后,按C-c
RET,就可以生成整个表格的结构。类似的快捷键还有很多:

创建和转换表格

快捷键 命令 说明
C-c 竖线 创建或转换成表格

调整和区域移动

快捷键 命令 说明
| 快捷键 | 命令 | 说明 |
|——–:|:—-:|:——————————-|
| C-c C-c | | 调整表格,不移动光标 |
| TAB | | 移动到下一区域,必要时新建一行 |
| S-TAB | | 移动到上一区域 |
| RET | | 移动到下一行,必要时新建一行 |

编辑行和列

快捷键 命令 说明
M-LEFT/RIGHT 移动列
M-UP/DOWN 移动行
M-S-LEFT/RIGHT 删除/插入列
M-S-UP/DOWN 删除/插入行
C-c - 添加水平分割线
C-c RET 添加水平分割线并跳到下一行
C-c ^ 根据当前列排序,可以选择排序方式

段落

对于单个回车换行的文本,认为其属于同一个段落。在导出的时候将会转化为不换行的同一段。如果要新起一个段落,需要留出一个空行。
这点与MediaWiki类似。

列表

Org 能够识别有序列表、无序列表和描述列表。

  • 无序列表项以 - 、=+= 或者 * 开头。
  • 有序列表项以 1. 或者 1) 开头。
  • 描述列表用 :: 将项和描述分开。
  • 有序列表和无序列表都以缩进表示层级。只要对齐缩进,不管是换行还是分块都认为是处于当前列表项。

同一列表中的项的第一行必须缩进相同程度。当下一行的缩进与列表项的的开头的符号或者数字相同或者更小时,这一项就结束了。
当所有的项都关上时,或者后面有两个空行时,列表就结束了。例如:

1
2
3
4
5
6
7
8
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.
Important actors in this film are:
- Elijah Wood :: He plays Frodo
- Sean Austin :: He plays Sam, Frodo's friend.

将显示为:

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.

Important actors in this film are:

Elijah Wood
He plays Frodo
Sean Austin
He plays Sam, Frodo's friend.

列表操作快捷键

为了便利,org-mode也支持很多列表操作的快捷键,大部分都与大纲的快捷键类似:

快捷键 命令 说明
TAB 折叠列表项
M-RET 插入项
M-S-RET 插入带复选框的项
M-S-UP/DOWN 移动列表项
M-LEFT/RIGHT 升/降级列表项,不包括子项
M-S-LEFT/RIGTH 升/降级列表项,包括子项
C-c C-c 改变复选框状态
C-c - 更换列表标记(循环切换)

分隔线

五条短线或以上显示为分隔线。

1
-----

标签

tag的作用

对于信息的管理,有分类(category)和标签(tag)两种方式。这两种方式各有特点:

通常分类是固定的,很少变化,而tag随时可以增加。
分类通常表现为树状结构,比较清晰,但是树状结构过于简单,不能表达复杂的信息。比如,如果有多个分类树,处理起来就会比较麻烦。

所以,这两种方式通常结合起来使用。比如blog系统中,通常既支持文章的分类(树),又支持为每篇文章作tag标记。

org-mode作为 最好的文档编辑利器
,在支持文内大纲(也是树状结构)的同时,还方便的支持tag功能。tag可以在多篇文档中共用。

标记tag

在Org-mode中,可以对标题增加tag标记。标记的格式如下:

1
跟特留尼西特握手                    :苦差:薪水:逃不掉:

而且Org-mode的标签自动按照大纲树的结构继承。即子标题自动继承父标题的标签。比如:

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

则最后一行标题具有 work, boss, notes, action 四个标签。

如果希望文档中的所有标题都具有某些标签,只需要定义文档元数据:

1
#+FILETAGS: :Peter:Boss:Secret:

如果手工输入标签,在标题后设置标签,键入:后,M-Tab自动提供标签的补齐。

更方便的做法是在正文部分用C-c C-q 或直接在标题上用C-c
C-c创建标签,这种方式可以列出所有预定义的标签以便选取。

预定义tag

上面提到,除了可以输入标签外,还可以从预定义的标签中进行选择。预定义的方式有两种:

  • 在当前文件头部定义

    1
    这种方式预定义的标签只能在当前文件中使用。使用#+TAGS元数据进行标记,如:

    :

    1
    #+TAGS: { 桌面(d) 服务器(s) }  编辑器(e) 浏览器(f) 多媒体(m) 压缩(z)

    每项之间必须用空格分隔,可以在括号中定义一个快捷键;花括号里的为标签组,只能选择一个

    对标签定义进行修改后,要在标签定义的位置按 C-c C-c 刷新才能生效。

  • 在配置文件中定义

    上面的标签定义只能在当前文件生效,如果要在所有的.org
    文件中生效,需要在 Emacs 配置文件 .emacs 中进行定义:

1
2
3
4
5
6
7
8
(setq org-tag-alist '(
(:startgroup . nil)
("桌面" . ?d) ("服务器" . ?s)
(:endgroup . nil)
("编辑器" . ?e)
("浏览器" . ?f)
("多媒体" . ?m)
))

默认情况下,org会动态维护一个Tag列表,即当前输入的标签若不在列表中,则自动加入列表以供下次补齐使用。

为了使这几种情况(默认列表、文件预设tags,全局预设tags)同时生效,需要在文件中增加一个空的TAGS定义:

1
#+TAGS:

按tag搜索

使用标签可以更好的管理内容。org-mode提供了以下功能:

KEYS COMMENT
C-c \ 按tag搜索标题
C-c / m 搜索并按树状结构显示
C-c a m 按标签搜索多个文件(需要将文件加入全局agenda)

可以使用逻辑表达式限制条件,更准确灵活的搜索

1
2
3
4
+     和   a+b     同时有这两个标签
- 排除 a-b 有 a 但没有 b
| 或 a|b 有 a 或者有 b
& 和 a&b 同时有 a 和 b,可以用“+”替代

在查询视图中 C-c C-c 退出。

导出和发布

更多: http://orgmode.org/manual/Exporting.html

Org-mode可以完美的编辑,但是最终文档可能需要发布成其他的格式。

Org-Mode 支持多种文档的输出,包括:

  • 文本
  • 网页
  • PDF(需要 Latex 支持)
  • XOXO
  • FreeMind/Xmind
  • Docbook
  • iCalendar(苹果 iCal 文件)
  • ……

准备工作

为了更好的发布文档,还需要做一些准备工作。主要是为文档添加一些”元数据“,使得发布的时候能更好地识别文档的内容。

文档元数据

具体包括:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#+TITLE:       the title to be shown (default is the buffer name)
#+AUTHOR: the author (default taken from user-full-name)
#+DATE: a date, an Org timestamp1, or a format string for format-time-string
#+EMAIL: his/her email address (default from user-mail-address)
#+DESCRIPTION: the page description, e.g. for the XHTML meta tag
#+KEYWORDS: the page keywords, e.g. for the XHTML meta tag
#+LANGUAGE: language for HTML, e.g. ‘en’ (org-export-default-language)
#+TEXT: Some descriptive text to be inserted at the beginning.
#+TEXT: Several lines may be given.
#+OPTIONS: H:2 num:t toc:t \n:nil @:t ::t |:t ^:t f:t TeX:t ...
#+BIND: lisp-var lisp-val, e.g.: org-export-latex-low-levels itemize
You need to confirm using these, or configure org-export-allow-BIND
#+LINK_UP: the ``up'' link of an exported page
#+LINK_HOME: the ``home'' link of an exported page
#+LATEX_HEADER: extra line(s) for the LaTeX header, like \usepackage{xyz}
#+EXPORT_SELECT_TAGS: Tags that select a tree for export
#+EXPORT_EXCLUDE_TAGS: Tags that exclude a tree from export
#+XSLT: the XSLT stylesheet used by DocBook exporter to generate FO file

其中#+OPTIONS是复合的选项,包括:

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
H:         set the number of headline levels for export
num: turn on/off section-numbers
toc: turn on/off table of contents, or set level limit (integer)
\n: turn on/off line-break-preservation (DOES NOT WORK)
@: turn on/off quoted HTML tags
:: turn on/off fixed-width sections
|: turn on/off tables
^: turn on/off TeX-like syntax for sub- and superscripts. If
you write "^:{}", a_{b} will be interpreted, but
the simple a_b will be left as it is.
-: turn on/off conversion of special strings.
f: turn on/off footnotes like this[1].
todo: turn on/off inclusion of TODO keywords into exported text
tasks: turn on/off inclusion of tasks (TODO items), can be nil to remove
all tasks, todo to remove DONE tasks, or list of kwds to keep
pri: turn on/off priority cookies
tags: turn on/off inclusion of tags, may also be not-in-toc
<: turn on/off inclusion of any time/date stamps like DEADLINES
*: turn on/off emphasized text (bold, italic, underlined)
TeX: turn on/off simple TeX macros in plain text
LaTeX: configure export of LaTeX fragments. Default auto
skip: turn on/off skipping the text before the first heading
author: turn on/off inclusion of author name/email into exported file
email: turn on/off inclusion of author email into exported file
creator: turn on/off inclusion of creator info into exported file
timestamp: turn on/off inclusion creation time into exported file
d: turn on/off inclusion of drawers

这些元数据可以根据需要设置。建议放在文档的开头部分。如,本文采用的元数据如下:

1
2
3
4
5
#+TITLE: org-mode: 最好的文档编辑利器,没有之一
#+AUTHOR:Holbrook Wong
#+EMAIL: wanghaikuo@gmail.com
#+KEYWORDS: emacs, org-mode
#+OPTIONS: H:4 toc:t

内容元数据

通常在行首以“#+”开头,可以有多种用途。创建内容元数据的区块可以用快捷键
< ? TAB=,其中 =? 为首字母,在下面的标题中列出。

  1. (v)分行区块

    默认内容不换行,需要留出空行才能换行。定义了分行的区块可以实现普通换行:

    1
    2
    3
    4
    5
    6
    #+BEGIN_VERSE
    Great clouds overhead
    Tiny black birds rise and fall
    Snow covers Emacs
    -- AlexSchroeder
    #+END_VERSE
  2. (q)引用区块

    通常用于引用,与默认格式相比左右都会留出缩进:

    1
    2
    3
    #+BEGIN_QUOTE
    缩进区块
    #+END_QUOTE
  3. (c)居中区块

    1
    2
    3
    4
    #+BEGIN_CENTER
    Everything should be made as simple as possible, \\
    but not any simpler
    #+END_CENTER
  4. (s)代码区块

    1
    2
    3
    4
    5
    #+BEGIN_SRC ruby
    require 'redcarpet'
    md = Redcarpet.new("Hello, world.")
    puts md.to_html
    #+END_SRC
  5. (e)例子

    1
    : 单行的例子以冒号开头

    :

    1
    2
    3
    4
    #+BEGIN_EXAMPLE
    多行的例子
    使用区块
    #+END_EXAMPLE
  6. (a)ASCII码

    TODO

  7. 表格与图片

    对于表格和图片,可以在前面增加标题和标签的说明,以方便交叉引用。

    比如在表格的前面添加:

    1
    2
    #+CAPTION: This is the caption for the next table (or link)
    #+LABEL: tbl:table1

    则在需要的地方可以通过 ref{table1} 来引用该表格。

(h)嵌入Html

对于导出html以及发布,嵌入html代码就很有用。比如下面的例子适用于格式化为cnblogs的代码块:

1
2
3
4
5
6
7
8
9
10
#+BEGIN_HTML
<div class="cnblogs_Highlighter">
<pre class="brush:cpp">
int main()
{
return 0;
}
</pre>
</div>
#+END_HTML

包含文件

当导出文档时,你可以包含其他文件中的内容。比如,想包含你的“.emacs”文件,你可以用:

1
#+INCLUDE: "~/.emacs" src emacs-lisp

可选的第二个第三个参数是组织方式(例如,“quote”,“example”,或者“src”),如果是
“src”,语言用来格式化内容。组织方式是可选的,如果不给出,文本会被当作
Org 模式的正常处理。用 C-c ,可以访问包含的文件。

嵌入 LaTex

对于需要包含数学符号和特殊方程的科学笔记,Org 模式支持嵌入 LaTeX
代码到文件中。你可以直接使用类 TeX
的宏来输入特殊符号,输入方程,或者整个 LaTeX 环境。

1
2
3
4
5
6
7
Angles are written as Greek letters \alpha, \beta and \gamma. The mass if
the sun is M_sun = 1.989 x 10^30 kg. The radius of the sun is R_{sun} =
6.96 x 10^8 m. If$a^2=b$and$b=2$, then the solution must be either
$a=+\sqrt{2}$or$a=-\sqrt{2}$.
\begin{equation}
x=\sqrt{b}
\end{equation}

特殊设置之后,导出 HTML 时 LaTeX 代码片断会生成图片并包含进来。

导出

做好准备工作后,就可以导出了。使用命令:

1
C-c C-e

然后选择相应的格式,就可以导出对应的文件了。

发布

Org 包含一个发布管理系统,可以配置一个由相互链接的 Org
文件组成的工程项目的自动向 HTML 转换。你也可以设置 Org, 将导出的 HTML
页面和相应的附件如图片,源代码文件等自动上传到服务器。

下面是一个例子:

1
2
3
4
5
6
7
8
9
(setq org-publish-project-alist
'(("org"
:base-directory "~/org/"
:publishing-directory "~/public_html"
:section-numbers nil
:table-of-contents nil
:style "<link rel=\"stylesheet\"
href=\"../other/mystyle.css\"
type=\"text/css\"/>")))

发布相关的命令:

命令 说明
C-c C-e C 提示指明一个项目,将所有的文件发布
C-c C-e P 发布包含当前文件的项目
C-c C-e F 只发布当前文件
C-c C-e E 发布所有项目

Org
用时间戳来查看文件是否改变。上面的命令只发布修改过的文件。你可以给它们加上前缀来强制重新发布所有的文件。

规则作为一种知识,其典型运用就是通过实际情况,根据给定的一组规则,得出结论。
这种规则的运用过程叫做推理。如果由程序来处理推理过程,那么这个程序就叫做推理机/推理引擎(Inference Engine)。
基于规则的推理机称为“规则引擎”。

什么是规则

在现实生活中,规则无处不在。我们最长接触的是法律、法规和各种制度;对于企业级应用来说,第一步的业务调研中很重要的内容就是了解业务规则。在企业流程再造中,可能还会接触到流程规则。

在IT技术领域,很多地方也应用了规则,比如路由表,防火墙策略,乃至角色权限控制(RBAC),或者Web框架中的URL匹配。

不管是哪种种规则,都规定了一组确定的条件和此条件所产生的结果。

举一个例子,是纷繁复杂的保险费率计算中的一条规则:

  • IF
    • 汽车是红色
    • 车是运动型的
    • 驾驶员是男性
    • 驾驶员在16-25岁之间
  • THEN
    • 保险费用增加20%

从这个例子可以看出:

  • 每条规则都是一组条件决定的一系列结果
  • 一条规则可能与其他规则共同决定最终结果。比如例子中的规则只产生了增量,还需要与确定基数的规则共同作用才能决定最终的费率
  • 可能存在条件互相交叉的规则,此时有必要规定规则的优先级

推理机与规则引擎

规则作为一种知识,其典型运用就是通过实际情况,根据给定的一组规则,得出结论。这个结论可能是某种静态的结果,也可能是需要进行的一组操作。
这种规则的运用过程叫做推理。如果由程序来处理推理过程,那么这个程序就叫做推理机/推理引擎(Inference Engine)。推理机是专家系统(专家系统是人工智能的一个分支)的核心模块。

推理引擎根据知识表示的不同采取的控制策略也是不同的,常见的类型包括基于神经网络、基于案例和基于规则的推理机。其中,基于规则的推理机易于理解、易于获取、易于管理,被广泛采用。这种推理引擎被称为“规则引擎”。

在规则引擎中,将知识表达为规则(rules),要分析的情况定义为事实(facts)。二者在内存中的存储分别称为Production Memory和Working Memory,如下图:

rules和facts是规则引擎接受的输入参数,而规则引擎本身包括两个组成部分:Pattern Matcher和Agenda。Pattern Matcher根据facts找到匹配的rules,Agenda管理PatternMatcher挑选出来的规则的执行次序。在外围,还会有一个执行引擎(Execution Engine)负责根据Agenda输出的rules执行具体的操作。

其中Pattern Matcher是规则引擎负责推理的核心。和人类的思维相对应,规则引擎中也存在两种推理方式:正向推理(Forward-Chaining)和反向推理(Backward-Chaining)。

正向推理也叫演绎法,由事实驱动,从 一个初始的事实出发,不断地应用规则得出结论。首先在候选队列中选择一条规则作为启用规则进行推理,记录其结论作为下一步推理时的证据。如此重复这个过程,直到再无可用规则可被选用或者求得了所要求的解为止。

反向推理也叫归纳法,由目标驱动,首先提出某个假设,然后寻找支持该假设的证据,若所需的证据都能找到,说明原假设是正确的;若无论如何都找不到所需要的证据,则说明原假设不成立,此时需要另做新的假设。

规则引擎的作用

规则引擎可以将规则的定义从代码中分离出来,将推理过程封装到规则引擎内部进行处理,这带来几个好处:

  1. 规则外部化,即有利于规则知识的复用,也可避免改变规则时带来的代码变更问题
  2. 由规则引擎使用某种算法进行推理过程,不需要编写复杂晦涩的逻辑判断代码
  3. 开发人员的不需要过多关注逻辑判断,可以专注于逻辑处理

多线程编程必须理解的一些基本概念,适用于所有编程语言。

并发式编程

不同的编程范式对软件有不同的视角。并发式编程将软件看做任务和资源的组合——任务之间竞争和共享资源,当资源满足时执行任务,否则等待资源。

并发式编程使得软件易于理解和重用,在某些场景能够极大提高性能。

多任务操作系统

要实现并发,首先需要操作系统的支持。现在的操作系统大部分都是多任务操作系统,可以“同时”执行多个任务。

多任务可以在进程或线程的层面执行。
进程是指一个内存中运行的应用程序,每个进程都有自己独立的一块内存空间。多任务操作系统可以“并发”执行这些进程。
线程是指进程中乱序、多次执行的代码块,多个线程可以“同时”运行,所以认为多个线程是“并发”的。多线程的目的是为了最大限度的利用CPU资源。比如一个JVM进程中,所有的程序代码都以线程的方式运行。

这里面的“同时”、“并发”只是一种宏观上的感受,实际上从微观层面看只是进程/线程的轮换执行,只不过切换的时间非常短,所以产生了“并行”的感觉。

多线程vs多进程

操作系统会为每个进程分配不同的内存块,而多个线程共享进程的内存块。这带来最直接的不同就是创建线程的开销远小于创建进程的开销。

同时,由于内存块不同,所以进程之间的通信相对困难。需要采用pipe/named pipe,signal, message queue, shared memory,socket等手段;而线程间的通信简单快速,就是共享进程内的全局变量。

但是,进程的调度由操作系统负责,线程的调度就需要我们自己来考虑,避免死锁,饥饿,活锁,资源枯竭等情况的发生,这会增加一定的复杂度。而且,由于线程之间共享内存,我们还需要考虑线程安全性的问题。

线程安全

因为线程间共享进程中的全局变量,所以当其他线程改变了共享的变量时,可能会对本线程产生影响。

所谓线程安全的约束是指一个函数被多个并发线程反复调用时,要一直产生正确的结果。要保证线程安全,主要是通过加锁的方式保证共享变量的正确访问。

比线程安全更严格的约束是”可重入性”,即函数在一个线程内执行的过程中被暂停,接下来又在另一个线程内被调用,之后在返回原线程继续执行。在整个过程中都能保证正确执行。保证可重入性,通常通过制作全局变量的本地拷贝来实现。

线程的生命周期

所谓的xx生命周期,其实就是某对象的包含产生和销毁的一张状态图。线程的生命周期如下图所示:

各状态的说明如下:

  • New新建。新创建的线程经过初始化后,进入Runnable状态。
  • Runnable就绪。等待线程调度。调度后进入运行状态。
  • Running运行。
  • Blocked阻塞。暂停运行,解除阻塞后进入Runnable状态重新等待调度。
  • Dead消亡。线程方法执行完毕返回或者异常终止。

可能有3种情况从Running进入Blocked:

  • 同步:线程中获取同步锁,但是资源已经被其他线程锁定时,进入Locked状态,直到该资源可获取(获取的顺序由Lock队列控制)
  • 睡眠:线程运行sleep()或join()方法后,线程进入Sleeping状态。区别在于sleep等待固定的时间,而join是等待子线程执行完。当然join也可以指定一个“超时时间”。从语义上来说,如果两个线程a,b, 在a中调用b.join(),相当于合并(join)成一个线程。最常见的情况是在主线程中join所有的子线程。
  • 等待:线程中执行wait()方法后,线程进入Waiting状态,等待其他线程的通知(notify)。

线程的类型

  • 主线程:当一个程序启动时,就有一个进程被操作系统(OS)创建,与此同时一个线程也立刻运行,该线程通常叫做程序的主线程(Main Thread)。每个进程至少都有一个主线程,主线程通常最后关闭。
  • 子线程:在程序中创建的其他线程,相对于主线程来说就是这个主线程的子线程。
  • 守护线程:daemon thread,对线程的一种标识。守护线程为其他线程提供服务,如JVM的垃圾回收线程。当剩下的全是守护线程时,进程退出。
  • 前台线程:相对于守护线程的其他线程称为前台线程。