日知录

学而不思则殆

使用 org-mode 管理日常事务

注:本文主要内容来自Emacs月月积累(终结篇):熟练使用org-mode管理日常事务

1 看懂 Org 文档

婴儿学说话都是从模仿开始的,这个方法对所有学习应该都有效。学习 org-mode 不妨先看看别人写的东西。org-mode 撰写的文档可以用任意文本编辑软件打开,最简单的 org 文档看起来是这样的:

* Introduction
** Summary
   Org is a mode for keeping notes, maintaining TODO lists, and doing project planning with a fast and effective plain-text system. .... 
** Installation
   Org is part of recent distributions of GNU Emacs, so you normally don’t need to install it. If, for one reason or another ** ... 
* Document structure
   Org is based on Outline mode and provides flexible commands to edit the structure of the document. 
** Outlines ...

这些文本只有两种元素:标题和普通段落。 以 * 符号开始的行表示该行为标题。

复杂一些的 org 文档可能看起来是下面这样的:

# -*- org -*- 
#+TITLE: org-mode 备忘录 
#+AUTHOR: ZGUANG@LZU 
#+STARTUP: content 
#+STARTUP: indent 
#+TODO: TODO STARTED | DONE 
<<目录位置>>
 *  列表
   + 选项1 
   + 选项2 
 * 表格
#+TBLNAME: 简单表格 
| Name | Value | SD | 
|-------+--------+------| 
| T1 | 1.2 | 0.14 | 
|-------+--------+------| 
| T2 | 2.3 | 0.11 | 
 * STARTED [80%] 超链接
 ** 网址链接
   [[http://www.gnu.org/software/emacs/][Download and install Emacs]] 
 ** 文件链接
   [[file:c:/windows/desktop.ini][桌面配置文件]] 
 ** 内部链接
   [[目录位置][返回目录]] 
 ** TODO 其他链接 
 * 代码块 :@待续: 
 #+BEGIN_SRC Emacs-lisp 
  (setq-default tab-width 4) ;设置TAB宽度为4字符 
 #+END_SRC 
 * TODO COMMENT 其他内容
 被注释的标题所包含的所有内容在文件导出时不会被显示

这些是普通文本,内容比飞机场还平坦,英文称为 plain-text,比中文名称直观。但是这么平坦的内容如果粘贴和保存为文本文件,用 Emacs打开,情况就不一样了:不仅有颜色,还有超链接。再用 C-c C-e h h 命令转成 HTML 文档然后打开,那就更不一样了( 自己试试 )。

上面的文本包含了些什么?虽然没有囊括 org-mode 的全部物件,但至少展示了几个方面的东西:

  • 以 # 号后加一空格开始的行表示注释,文件导出时这些内容不被导出,上面第一行就是。
  • 以 #+ 符号开始的行用于设置文档参数或内容属性,比如文档的标题、作者,org-mode打开时文档的呈现状态等。
  • 用 [[]] 括起来的内容表示外部链接
  • 用 <<>> 括起来的内容表示文档的内部链接
  • 以 * 符号开始的行,表示该行为标题。
  • 标题内容前的 TODO 标记是待办任务的标记符号。
  • 标题行后面两个 : 符号间的内容表示标签( TAG )。
  • 标题行如果标题文本前有 COMMENT 标记表示该标题下的所有内容为注释。
  • 位于 #+BEGIN_XXX 和 #+END_XXX 之间的内容为特殊文档块,如代码块、例子、引用等。

虽然东西不少,但对某人来说不是所有的都要用到,所以建议用到了再去了解。

1.1 进入 Org 模式

安装 Emacs 的步骤就不说了,到这地步相信都有了一定的基础。直入正题吧:

  • 打开后缀名为 org 的文件自动进入 org-mode 模式
  • 在 init.el 配置文件中设置某类文件的编辑模式为 org,如 txt 类文件:
(add-to-list 'auto-mode-alist '("\\.txt\\'" . org-mode))
  • 用 Emacs 打开文件后使用主模式选择命令( M-x org-mode )
  • 任意文件名,如果文件的第一个非空行包含: -*-org-*- ,用 Emacs 打开该文件后会自动使用 org-mode 模式。

后面这种方式对于使用 Emacs 编辑程序文件尤其方便,无需改变文件的后缀名。

2 标题和基于标题的编辑

标题是 Org 组织文档的基础,它在 Org 中的作用怎么强调都不过分。要用好 Org-mode 首先要学会标题的定制和使用,必须的,其他杂七杂八的东西都可以暂缓,有些内容甚至可以当它们不存在。

2.1 设定标题

对于传统意义的标题,Org的设定非常简单:在行首加星号,星号与标题文字之间至少有一个空格,星号的数量表示标题的级别,方法简单明了。你不用为字体、 行间距、缩进等设置而烦恼,专心做自己的事情。事实上标题是 Org 文档句法中唯一不需要通过上下文关系就能确定的内容:一行文本是不是标题只需要看行首字 符。例如:

* 一级标题 
** 二级标题
*** 三级标题
正文内容 
* 其他一级标题

然而,为使标题适应更广泛的应用(不仅仅是表明文档的结构层次),Org对其进行了较复杂的定义。它的完整语法为:

STARS KEYWORD PRIORITY TITLE TAGS

其中:

  • STARS 即星号,这是一个标题唯一必要的内容,其他(包括标题名称)都可以省略。
  • KEYRORD 为TODO关键词,大小写敏感。
  • PRIORITY 为优先级选项,为#号加一个字符并用方括号括起来,如 [#A]
  • TITLE 即为实际的标题文本
  • TAGS 为标签。

下面是一个完整标题的例子:

** TODO [#2] 优先级为2的待办事项 :@家庭作业:

虽然 TODO 关键词、优先级和标签属于标题的成分,但由于设定较复杂而且功能重要,有关内容将在后面介绍。

2.2 基于标题的文档编辑

Org 基于标题的文档编辑方式允许用户在非常简洁的显示模式下对某个或多个标题下的所有内容进行复制、粘贴、移动等操作,相当方便,真正实现了标题在文档管理中的组织者作用。

2.2.1 术语约定

  • 标题:仅指标题定义行
  • 子标题:大标题下属的小标题
  • 标题树:包括标题、子标题及其下属的所有文本
  • 大纲:或文档轮廓,即全部标题,是一种显示模式
  • 大纲折叠:隐藏子标题树
  • 大纲展开:分级显示子标题树

2.2.2 在标题间移动光标

快捷键 动作
C-c C-p/n 移动到上/下一个标题
C-c C-b/f 移动到同级别的上/下一个标题

2.2.3 大纲的折叠与展开

  • 手动操作:
快捷键 动作
TAB 局部命令,循环使用可以折叠/展开光标所在位置的标题树
S+TAB 全局命令,循环使用可以折叠/展开整个文档的标题树
  • 设定文档属性:
    • #+STARTUP: overview
    • #+STARTUP: content
    • #+STARTUP: showall
    • #+STARTUP: showeverything

2.2.4 标题编辑

快捷键 动作
M-LEFT/RIGHT 升级/降级当前标题,不允许有子标题的存在
M-S-LEFT/RIGHT 升级/降级标题树,即标题树内的各级标题相应升/降级
M-UP/DOWN 在同级标题间上/下移标题树,不能跨级别移动
M-RET 在当前标题后插入同级标题符号(即换行符和星号)
C-RET 在当前标题树后插入同级标题符号
M-S-RET 在当前标题后插入同级TODO标题
C-S-RET 在当前标题树后插入同级TODO标题
C-c * 把光标所在行转成标题
C-c - 把光标所在行转成列表

2.2.5 使用 Tips

Org-mode 很多编辑命令的使用与光标所处的位置有关,同一个键盘命令如果光标位于不同文本环境可能会有不同的作用,这些命令称为局部命令。例如 C-c * 命令,如果光标位于普通文本或列表项内,它的作用是将该行转成上一级标题的子标题;如果该行已经是标题,则将其变为普通文本;如果在选区内执行该命令,把 选区内所有行转成标题;如果选区内第一行是列表,仅把第一行转成标题;如果选区内第一行是标题,则把选区内所有标题行都转成普通文本。

3 用 Org 管理待办任务

Org 扩展了标题的定义,增加了关键词、优先级和标签等元素。这些元素不仅使标题在文档组织发挥更重要的作用,标题的功能也得到了扩展。Org 对日程的管 理就是基于标题进行的:只要会设定标题就可以用 Org 管理日程。虽然道理是这样,但要熟练使用 Org 的日程管理功能还掌握比较多的东西。

3.1 定制任务和状态

3.1.1 设置 TODO 关键词

TODO 关键词是用来表示任务状态或类型的词。Org 默认的 TODO 关键词只有两个:TODO 和 DONE,但很容易自定义其他的关键词。TODO 关键词分为两种。 一种是状态关键词,比如“等待”、“开始”和“完成”等,事件处理的过程中其处理状态按关键词顺序从前往后转换。另一种是类型关键词,按事件的轻重缓急分 为“紧急”、“优先”、“普通”和“完成”等类型,但事件只有未完成和完成两种状态,所以处理结束后将直接转到“完成”类型,而“紧急”、“优先”和“普通”这些类型之间不能相互转换。

  • 在 Org 文件中定义 TODO 关键词

    在 Org 文件中定义的 TODO 关键词仅适用于当前文件。状态关键词使用 #+SEQ_TODO: 定义,类型关键词使用 #+TYP_TODO: 定义。可以定义多系列的 TODO 关键词,可以使用中文关键词。

    #+TYP_TODO: 工作(w!) 学习(s!) 休闲(l!) | 
    #+SEQ_TODO: PENDING(p!) TODO(t!) | DONE(d!) ABORT(a@/!)
    
    • “|”用来分隔“未完成”和“完成”两种状态的关键词,前面为未完成项,后面为完成项。如果没有“|”符号,最后一个关键词将被设为完成项,其余为未完成项。
    • 关键词后括号内的字母为快捷选择键,当使用 C-c C-t 设置或改变当前标题的TODO状态或类型时将出现选项菜单,此时可以用快捷键进行选择。
    • 括号内的“!”表示时间戳,设置或改变到该状态时(直接输入关键词不算)将同时插入当前时间
    • 括号内的“@”表示切换到该状态时需要输入文字说明,比如任务取消、流产或失败的原因。
    • 输入后将光标置于该行内使用 C-c C-c 命令可使该定义立刻生效。
  • 在 Emacs 配置文件中定义 TODO 关键词

    如果经常使用 Org 进行日程管理,应该在 Emacs 配置文件中定义常用的 TODO 关键词,这些定义对所有文件都适用。方法是设置 org-todo-keywords ,如:

    (setq org-todo-keywords '((type "工作(w!)" "学习(s!)" "休闲(l!)" "|") 
    (sequence "PENDING(p!)" "TODO(t!)" "|" "DONE(d!)" "ABORT(a@/!)") ))
    
  • 改变 TODO 关键词的外观

    仅通过文字对于事件进行分类总嫌苍白无力,能用不同颜色的标签对日程表的事件进行强化分类就会好得多。这一功能可以通过设置 TODO 关键词的外观变量 org-todo-keyword-faces 实现。如:

    (setq org-todo-keyword-faces '
    (("工作" . (:background "red" :foreground "white" :weight bold)) 
    ("学习" . (:background "white" :foreground "red" :weight bold)) 
    ("休闲" . (:foreground "MediumBlue" :weight bold)) 
    ("PENDING" . (:background "LightGreen" :foreground "gray" :weight bold)) 
    ("TODO" . (:background "DarkOrange" :foreground "black" :weight bold)) 
    ("DONE" . (:background "azure" :foreground "Darkgreen" :weight bold)) 
    ("ABORT" . (:background "gray" :foreground "black"))
    ))
    

3.1.2 标题型任务和子任务

Org 主要通过标题的 TODO 关键词对待办任务(下面称为任务)进行管理,由于标题是分级的,所以这种管理方式很自然地支持子任务:子标题即子任务。Org 的任务定义跟标题定义一样简单,有三种方式:

  • 直接在标题中的 KEYWORD 位置输入 TODO 关键词
  • 使用 C-c C-t 快捷键呼出关键词选择菜单
  • 使用 S-LEFT/RIGHT 快捷键快速设置 TODO 关键词

当然也可以在标题编辑时直接使用 M-S-RET 或 C-S-RET 插入 TODO 标题。

3.1.3 非标题型子任务

Org的任务主要由标题定制,但也提供了非标题型子任务的设置。对于以“[ ]”开头的列表, Org 把它们当作复选框,复选框各选项的选择状态表示完成状态。例如:

  • 研究内容 [1/2]
    • [X] 研究内容1
    • [-] 研究内容2 [1/2]
      • [ ] 小内容1
      • [X] 小内容2

复选框有三种状态:未完成、完成和中间状态(如上),可以使用快捷键 C-c C-c 或 C-c C-x C-b 修改。

Org 自动将复选框列表的完成状态纳入上一级任务的监控,具体使用说明参看任务进度监控。

3.2 任务优先级

你可以设置足够的 TODO 关键词和外观用来区分待办任务的类型、状态和优先级,但是这不仅使任务设置复杂化,还会导致任务间的关系十分混乱。Org 为任务优先级留有专门的位置,即标题的 PRIORITY 位置。 Org 预定义了任务的三个优先级即 [#A], [#B] 和[#C] ,用于区分类型任务的优先级别。如果不设置任务优先级,默认为 B 级。

不同优先级的任务在产生日程表时按优先级别先后排列,而其他时候则没有任何差别。为了充分发挥任务优先级的作用,最好在 Emacs 配置文件中对优先级的范围和外观进行自定义,例如:

;; 优先级范围和默认任务的优先级 
(setq org-highest-priority #A) 
(setq org-lowest-priority #E) 
(setq org-default-priority #E) 
;; 优先级醒目外观 
(setq org-priority-faces '(
(#A . (:background "red" :foreground "white" :weight bold)) 
(#B . (:background "DarkOrange" :foreground "white" :weight bold)) 
(#C . (:background "yellow" :foreground "DarkGreen" :weight bold)) 
(#D . (:background "DodgerBlue" :foreground "black" :weight bold)) 
(#E . (:background "SkyBlue" :foreground "black" :weight bold)) ))

设置 TODO 关键词和优先级后标题的外观如下:

在标题上使用 S-UP/DOWN 可以选择和改变任务的优先级。

3.3 任务标签

对于Org老手来说,用TODO关键词和优先级区分任务就足够了。如果不能满足需要,还可以使用标签。在 Org中,标签定义于标题行末端,位于两个或两个以上冒号之间,它为待办任务提供了进一步的分类方法。

3.3.1 标签命名规则

  • 位置:标签只能在各级标题的行末端定义,即只有标题文字可以拥有标签
  • 命名:标签的名字可以是包含字母、数字、下划线 _ 或@符号的字
  • 包含在一对“:”号之间,如:
* HEADLINE 1 :label1:
  • 一个标题可以有多个标签名称,定义方法如:
** HEADLINE 2 :label2:label3:

3.3.2 标签编辑命令

标签可以直接在标题后手工输入,Org 也提供了快捷的编辑命令:

  • 在文内使用 C-c C-q 命令,输入标签名称并回车,标签自动产生并放置到该文所属标题的标签列
  • 如果光标在一个标题内,使用 C-c C-c 命令的作用和 C-c C-q 一样,但如果不在光标不在标题内则不起作用。
  • 在合适的位置再次使用 C-c C-q 或 C-c C-c 即可对现有标签名称进行修改。

3.3.3 预定义标签

和 TODO 关键词一样,标签可以预定义并设置快捷选择键,在使用标签编辑命令时将弹出选择菜单: 在 Emacs 配置文件中定义的标签应用于所有文件。例如:

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

在org文件中定义该文件使用的标签。例如:

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

3.3.4 标签的继承特性

设置了标签的任务能自动将所设标签属性传递给子任务,称为标签的继承性。这一特性使标签尤其适用于任务的分类。

* TODO 任务1 :紧急任务: ** TODO 子任务1 :特急: ** TODO 子任务2

子任务1和子任务2无需显式贴上 :紧急任务: 就自然拥有该标签,子任务1实际有两个标签 :紧急任务:特急: 。

标签外观也可以修改,方法同 TODO 关键词的外观修改差不多,设置 org-tag-faces 变量。

3.4 任务间的依赖关系

3.4.1 任务属性

标题不可能包罗万象,一些任务属性如任务 ID 不能通过任务标题设定。这些属性可以通过 Org 文档的内容属性设定.属性定义以 PROPERTIES 名称开头,以 END 结束,每项内容均使用两个冒号括起来,如:

 * TODO 今日事物 
  :PROPERTIES: 
:ID: today-todos 
:ORDERED: t 
:COOKIE_DATA: todo recursive 
:END:

3.4.2 简单任务关系

现版Org-mode实现了两种简单任务关系的设置: -如果子任务没有全部完成,主任务将不能设置为 DONE 状态

  • 如果前面有其他任务没有完成,后面的任务将不能设置为 DONE 状态

要使用第一种依赖关系需要打开 org-enforce-todo-dependencies ,即在 Emacs 配置文件中设置:

(setq org-enforce-todo-dependencies t)

要使用第二种依赖关系则需要在主任务下打开任务的 ORDERED 属性,例如:

 * TODO 请客吃饭 
:PROPERTIES: 
:ORDERED: t 
:END: 
 ** TODO 确定客人时间 
 ** TODO 订饭店 
 ** TODO 点菜 
 ** TODO 买单

请客吃饭下的各项工作得按顺序去做。

3.4.3 复杂依赖关系

对于大型项目,各项任务间的关系错综复杂,利用上面的简单任务关系根本无法进行有效项目进程规划。使用 org-depend.el 程序(自己查找下载)对这类项目的日程安排很有帮助。该程序附带了应用例子,这里只介绍它的功能(由程序内的说明翻译而来)。

  • 触发事件
    • 一个任务如果具有 TRIGGER 属性,而且属性值为 chain-siblings(KEYWORD) 字串,当该任务的状态转到 DONE 时将触发事件:该任务的下一个同级任务转为 KEYWORD 状态并获得相同的 TRIGGER 属性
    • 一个任务如果具有 TRIGGER 属性,而且属性值为 chain-siblings-schedualed 字串,当该任务的状态转到 DONE 时将触发事件:该任务的下一个同级任务获得相同的计划时间并获得相同的 TRIGGER 属性
    • 一个任务如果具有 TRIGGER 属性,而且属性值为 chain-find-next(KEYWORD[,OPTIONS]) 字串,当该任务的状态转到 DONE 时将触发以下事件:
      • 收集所有同级任务到一个临时列表,然后按照 OPTIONS 进行过滤和排序
      • 列表中第一个任务的状态转为 KEYWORD 状态并获得相同的 TRIGGER 属性
      • OPTIONS 选项由逗号分隔,不能有空格,取值可以为: from-top, from-bottom, from-current, no-wrap, today-only, today-and-done-only, priority-up, priority-down, effort-up, effort-down
    • 如果 TRIGGER 属性包含任何其他的字符串,这些字符串都被当成id处理,例如: XYZ(KEYWORD) ,org-mode将查找ID属性为 XYZ 的任务并将其状态该为 KEYWORD 状态。
  • 阻止事件
    • 如果一个任务具有 BLOCKER 属性,且属性值为 previous-sibling ,那么试图将该任务转到 DONE 状态时将检查上一个任务的状态。如果上一个任务的状态为 TODO ,当前任务的状态不能改变
    • 如果一个任务具有 BLOCKER 属性,且属性值包含其他的字符串,这些字符串将被当成任务的 ID。试图改变当前任务状态为 DONE 时 org-mode 将查找相应 ID 的任务,如果这些任务中有任何一个还不是 DONE 状态,当前任务的状态将不能改变
    • 如果状态改变被阻止,该任务将被打上 :blocked: 标签,这样你可以使用 C-c & 找到阻止该事件的任务。

3.5 预约任务时间

3.5.1 Emacs 日历

Emacs提供了桌面日历,不仅附带有公共事件日志(节假日等),还可以帮助你管理预约事件和跟踪项目时间。Emacs日历使用独立的缓冲区和主模式(Calendar模式),执行 M-x calendar 命令即可打开并显示3个月的日历,当前月份居中。如果要打开特定时间的日历,用 C-u M-x calendar ,在提示符下输入年(数字)和月(名称)即可。鼠标键在日历模式下具有特殊意义:左键(Mouse-1)选定某天,中键(如果有,Mouse-2)弹出适用于整个日历的命令菜单,右键(Mouse-3)弹出适用于鼠标所指日期的菜单。键盘输入 q 直接退出日历(关闭日历窗口)。

  • 在日历中移动光标
    命令 动作 变量
    C-f 前移一天 calendar-forward-day
    C-b 后移一天 calendar-backward-day
    C-n 前移一周 calendar-forward-week
    C-p 后移一周 calendar-backward-week
    M-} 前移一月 calendar-forward-month
    M-{ 后移一月 calendar-backward-month
    C-x ] 前移一年 calendar-forward-year
    C-x [ 后移一年 calendar-backward-year
    命令 动作 变量
    C-a 到周的开始 calendar-beginning-of-week
    C-e 到周的结束 calendar-end-of-week
    M-a 到月的开始 calendar-beginning-of-month
    M-e 到月的结束 calendar-end-of-month
    M-<</td> 到年的开始 calendar-beginning-of-year
    M-> 到年的结束 calendar-end-of-year
    命令 动作 变量
    g d 到指定年月日 calendar-goto-date
    g D 到某年的第几天 calendar-goto-day-of-year
    g w 到某年的第几周 calendar-iso-goto-week
    o 把某年某月居中 calendar-other-month
    . 到今日(不居中) calendar-goto-today
  • 卷动日历

    和移动鼠标有些差别。

    命令 动作 变量
    > 前卷一个月 calendar-scroll-left
    <</td> 后卷一个月 calendar-scroll-right
    C-v 前卷三个月(下一屏) calendar-scroll-left-three-months
    M-v 后卷三个月(上一屏) calendar-scroll-right-three-months
  • 使用农历

    Emacs 日历可以转换农历,不过现在你不需要自己去做了,下载使用 cal-china-x 即可。下载后放到某个位置,如 .emacs.d/addons ,在 Emacs 配置文件中添加两行:

    (add-to-list 'load-path "~/.emacs.d/addons")
    (require 'cal-china-x)
    
  • 节日和日志

    为简单起见,凡在日历上标示的事件(节日、生日、纪念日或其他)下面都称为节日:

    命令 动作
    x 在日历窗口中标出节日
    u 取消节日标记
    h 显示当前日期的节日
    a 列出当前日历(三个月)的所有节日
    M-x holidays 在另一个窗口列出近3个月(以今天为中心)的所有节日
    M-x list-holidays 在另一窗口列出设定的若干年内的所有节日

    Emacs 日历默认不标记节日,如果希望打开日历就能看到节日标记,设置一下:

    (setq mark-holidays-in-calendar t)
    

    公共“节日”很多,一些可能是你根本不 care 的,如果这些都出现在日历和日程表中,肯定很烦人。所以还得定制一下,只显示自己设定的日历事件,比如:

    (setq my-holidays '(
    ;;公历节日
    (holiday-fixed 2 14 "情人节")
    (holiday-fixed 9 10 "教师节") 
    (holiday-float 6 0 3 "父亲节") 
    ;; 农历节日 
    (holiday-lunar 1 1 "春节" 0) 
    (holiday-lunar 1 15 "元宵节" 0) 
    (holiday-solar-term "清明" "清明节") 
    (holiday-lunar 5 5 "端午节" 0) 
    (holiday-lunar 7 7 "七夕情人节" 0) 
    (holiday-lunar 8 15 "中秋节" 0)
    ;;纪念日 
    (holiday-fixed 1 1 "儿子生日") 
    (holiday-lunar 2 2 "老婆生日" 0) 
    (holiday-lunar 3 3 "我的生日" 0) )) 
    (setq calendar-holidays my-holidays);只显示我定制的节假日
    

    其中:

    • holiday-fixed 用于设定公历事件
    • holiday-float 用于设定浮动公历事件
    • holiday-lunar 用于设定农历事件,各项的意义参考后面的 diary-float 说明。
    • holiday-solar-term 是一些预定义但还需要特殊计算的节日,如农历的24节气。

3.5.2 Org-mode 时间戳的组成

时间戳由尖括号 <> 或方括号 [] 表示,前者为激活时间,后者为非激活时间(不加入日程表的时间)。括号内可以包括以下内容组成(按先后顺序):

  • 日期,如 2013-6-1
  • 时间或时间范围,如 2:30pm 或 10:00-12:00
  • 表示周期重复的字符串,如 +1w 表示每周重复
  • 其他附加信息和特殊符号:

符号 意义 +0 今天 . 今天 +4d 今天算起,第4天 +4 同上 +2w 今天算起,第2周 ++5 默认日期开始,5天后 +2tue 今天算起,第2个Tuesday

注意“今天”和“默认日期”所表示的意义是不同的,例如:

  • <2013-06-20 周四 .+1w> 表示这是一个周期性重复任务,每周四执行;但是如果某次任务的实际完成日期( DONE 状态产生日期)是星期一,那么下一次任务就是一周后的星期一
  • <2013-06-20 周四 ++1w> 同样表示一个周期性重复任务,每周四执行;但不管任务实际完成日期是星期几,下一次任务的时间都固定为下个星期四

由两个断线“–”连接起来的两个时间戳表示时间段,如: <2013-06-25 星期二>–<2013-06-26 星期三> 除以上标准用法外,一些不规则时间戳可以使用Emacs日志风格的字符串表示,同样放在方括号或尖括号中。常用的有:

  • 周年纪念,如毛泽东诞辰: %%(diary-anniversary 12 26 1893)
  • 周期重复,如从6月1日开始每隔10天重复: %%(diary-cyclic 10 6 1 2013)
  • 某些日期,用于组合不同的月、日、年,例如每年的3-5月的10号可以这么表示(t表示所有数值,这里表示所有年度): %%(diary-date '(3 4 5) 10 t)
  • 某月的第几个星期几,用浮动日期格式字符串 %%(diary-float month dayname index) 表示。其中 month 为表示月份的整数(同样可以使用t表示所有月份), dayname 表示星期几(0为Sunday), index 为正数表示从前往后数,复数则相反。如5月的最后一个星期三表示为: %%(diary-float 5 3 -1)

3.5.3 产生时间戳

时间戳可以直接输入,但最好使用快捷命令(期间要调用 Emacs 日历)产生:

快捷命令 动作
C-c . 通过日历选择计划日期,如果在一个时间戳后面使用将产生一个日期段
C-c ! 同上,但产生非激活日期
C-u C c . 产生计划时间或时间段
C-u C c ! 同上,但产生非激活日期
C-c C-c 在时间戳上使用该命令将对该时间戳进行格式补全和校对
C-c <</code> 插入 Emacs 日历中光标所在处的日期(或当前日期)作为时间戳
C-c > 访问 Emacs 日历上当前日期;如果光标处有时间戳就访问该日期
C-c C-o 在日程表上访问光标时间戳表示的日期/时间
S-UP/DOWN/LEFT/RIGHT 前/后移日期或时间(小时/分),具体情况由光标所在位置而定

3.5.4 预约任务时间

  • 安排开始时间(SCHEDUALED)

    表示任务将在指定的时间开始。计划时间通过 C-c C-s 命令输入,例如

    SCHEDULED: <2013-06-25 周二>
    

    一个任务在计划时间到达时将在每天的日程表上出现,直到任务标记为 DONE 。也可以延迟计划任务在日程表上显示的时间,如延迟2天:

    SCHEDULED: <2013-06-25 周二 -2d>
    

    注意这里“计划时间”和通常所说的安排一个任务的时间不一样。如果要指定一个任务在确切的时间开始,直接输入时间戳就可以了。

  • 设定截止时间(DEADLINE)

    任务应该设置完成的截止时间。截止时间通过 C-c C-d 命令输入,例如:

    DEADLINE: <2013-06-26 周三 -5d>
    

    日期后面的 -5d 表示截止时间前5天开始在 today 日程表上提醒。如果不设置提醒开始时间则按照 org-deadline-warning-days 的设置进行提醒。日程提醒将一直持续(即使任务过期),直到任务标记为 DONE 状态。如果一个任务既安排了开始时间又设定了截止时间,日程表上的提醒将有重复,可以选择显示哪个。忽略截止时间提醒的设置为:

    (setq org-agenda-skip-deadline-prewarning-if-scheduled t)
    

    忽略开始时间提醒的设置为:

    (setq org-agenda-skip-scheduled-delay-if-deadline t)
    
  • 安排周期重复任务的时间

    和前面的重复任务时间戳没什么不同,只不过要注意表示重复和表示提醒安排的字符串的顺序,表示重复的在前,如:

    DEADLINE: <2013-11-01 周五 +1m -3d>
    

3.6 任务进程监控与记录

3.6.1 任务进度监控

  • 显示进度

    在标题或复选框列表(不一定是任务)的任何位置输入 [%][/] ,当使用 C-c C-t 或 S-LEFT/RIGHT 改变子任务的状态时 Org 就会计算完成百分比或分数,如 [1/5] 。通过输入改变 TODO 关键词状态的方式不触发计算,但可以在进度状态的位置上执行 C-c C-c 命令更新状态。

  • 设置统计方式

    默认情况下任务的进度监控仅计算下一级子任务,要统计所有级别的子任务应在合适的位置设置 :COOKIE_DATA: todo recursive 属性,即:

    :PROPERTIES: :COOKIE_DATA: todo recursive :END:
    

    如果监控的是复选框任务,把 todo 改为 checkbox 。

3.6.2 状态更改记录

如果 TODO 关键词定义时设置了时间标签选项(!),任务状态发生改变时将在该任务的下方记录下状态改变的时间。这项功能很容易使用。如果不想记录某个任务及其子任务的状态更改,可以在任务下设置属性 LOGGING 为 nil 。

* 本项任务无需记录状态改变 :PROPERTIES: :LOGGING: nil :END:

3.6.3 关闭任务

如果觉得通过设置 TODO 关键词方式记录的状态更改时间很烦人(每次修改都记录,即使误操作了也要手工删除),那你应该用 org-log-done 变量:

(setq org-log-done 'time)

如上设置后每次将任务改变为 DONE 状态时在任务下添加一行内容 CLOSED: [timestamp] ,而再将 DONE 状态改为 TODO 时该行内容被自动删除。 如果项目结束时你还想对它写点评价子类的话,可以设置

(setq org-log-done 'note)

这样每次任务结束时 Org 就会提示你输入备注,并把它放到“Closing Note”标题下。

3.6.4 工作计时和癖好记录

我仅粗略看了一下工作计时这个功能的一些介绍。按我的理解,它主要用于写作上,允许你记录和计算你趴在某个标题下的时间。一般人可能不干这么无聊的事情。我对癖好记录(habits tracking)也没什么兴趣。自己看 The Org Manual 吧。

3.7 使用日程表管理任务

3.7.1 日程表视图(Agenda views)

Org-mode 不要求所有的待办任务都整齐排列到一个文件中,更没有设立专门的诸如.todo类型的文件,因为它的作者们认为我们平时要处理的事情多数 都是在记笔记中产生的。任务可以随时随地定制,它们会散落到各个角落(即文件),因此必需使用某些方式把它们收集起来并进行排序和显示。Org能够使用一 些标准选择任务并显示在独立的缓冲区中。它提供了7种不同的显示模式:

  • 日程表:用类似于日历的方法显示特定日期的任务
  • 待办任务列表:列出所有未完成的任务
  • 匹配视图:通过标签、属性或TODO关键词选择并显示匹配的标题
  • 时间线视图:把所有任务放到一个Org文件中并按时间顺序排列
  • 文本搜索视图:从多个文件中搜索匹配特定关键词的任务
  • 静止项目视图:列出没有任何动静的项目(标题),即没有任何TODO关键词标记的标题
  • 用户定制视图:可以定制特殊搜索条件或组合不同的视图

3.7.2 日程表文件

Org虽然没有定义专门的日程表类型的文件,但要产生特定的日程表总不能天南海北的胡乱查找任务,所以要先指定一些(org)文件为搜索范围。这可以通过设置 org-agenda-files 变量完成,如:

(setq org-agenda-files (list "D:/agenda"))

会把 D:/agenda 目录下(不包括子目录)的所有 org 文件都加入到日程表的搜索范围。也可以使用下面的快捷键逐个添加或删除:

  • C-c [ :把当前文件加到 agenda-files 列表的最前面;如果文件已经在 agenda-files 中,就把移到最列表最前面或最后面。
  • C-c ] :把当前文件从 agenda-files 列表移除

3.7.3 在日程表上查看任务

Org-mode 产生日程表的快捷键默认不安装,得自己设置:

(global-set-key "\C-ca" 'org-agenda)

使用 C-c a 就会弹出日程表视图选择窗口,每个选项都有说明,其中包括前面所说的几种日程表视图,不再啰嗦。 日程表默认列出7天内的任务,如果要改变就设置 org-agenda-ndays 变量,如:

(setq org-agenda-ndays 21) 
(setq org-agenda-include-diary t)

3.7.4 用 Org 文件定制特殊日程表事件

这是个很 fancy 的功能,类似于 Emacs 日历的日志文件管理方式,值得使用。比如:

* 纪念日 
  #+CATEGORY: Ann %%(org-anniversary 1999 1 1)
  结婚 %d 周年纪念 %%(org-anniversary 2000 2 2) 
  儿子 %d 岁生日

保存为一个独立的 org 文件,然后加入你的日程表文件列表,产生日程表时会这些事件。

4 快捷键备忘

4.1 标题操作

移动  
C-c C-p/n 移动到上/下一个标题
C-c C-b/f 移动到同级别的上/下一个标题
折叠  
TAB 局部命令,循环使用可以折叠/展开光标所在位置的标题树
S+TAB 全局命令,循环使用可以折叠/展开整个文档的标题树
编辑  
M-LEFT/RIGHT 升级/降级当前标题,不允许有子标题的存在
M-S-LEFT/RIGHT 升级/降级标题树,即标题树内的各级标题相应升/降级
M-UP/DOWN 在同级标题间上/下移标题树,不能跨级别移动
M-RET 在当前标题后插入同级标题符号(即换行符和星号)
C-RET 在当前标题树后插入同级标题符号
M-S-RET 在当前标题后插入同级TODO标题
C-S-RET 在当前标题树后插入同级TODO标题
C-c * 把光标所在行转成标题
C-c - 把光标所在行转成列表
S-LEFT/RIGHT 快速设置 TODO 关键词

4.2 todo 关键词

定义与设定  
#+TYP_TODO: 工作(w!) 学习(s!) 休闲(l!)
#+SEQ_TODO: PENDING(p!) TODO(t!) DONE(d!) ABORT(a@/!)
(setq org-todo-keywords '((type "工作(w!)" "学习(s!)" "休闲(l!)" )
  (sequence "PENDING(p!)" "TODO(t!)" "DONE(d!)" "ABORT(a@/!)") ))
“!” 设置或改变到该状态时,插入当前时间
@ 切换到该状态时需要输入文字说明
C-c C-c 使定义生效
C-c C-t 在关键字之间切换

4.3 日程计划

定义与设定  
C-c C-s 指定开始时间 SCHEDULED: <2013-06-25 周二 >
C-c C-d 设定截止时间 DEADLINE: <2013-06-26 周三 -5d>
C-c [ 把当前文件加到 agenda-files 列表的最前面
C-c ] 把当前文件从 agenda-files 列表移除
(global-set-key "\C-ca" 'org-agenda) 配置文件中启用“日程表生成”快捷键
C-c a 弹出日程表视图选择窗口

Comments

使用Disqus评论 使用多说评论
comments powered by Disqus