目录
- 1 创建任务文件
- 2 设置基础任务状态
- 3 捕获 - 快速记录任务
- 4 事件优先级
- 5 Timestamp(时间戳)
- 5.1 基本形式
- 5.2 重复间隔
- 5.3 修改默认提醒时间
- 5.4 重复事件的表示
- 6 任务进度状态跟踪
- 6.4 标题子任务
- 6.5 复选框子任务
org-mode 另一个用途是可以管理自己的任务清单。任务清单管理和日程管理是有区别的,日程管理重点是“在什么时间做什么事”,而任务清单管理重点则是“清空大脑,让系统记住有哪些事需要做,安排在什么时间做”。
1 创建任务文件
通常我们把任务放在专门的任务文件中,便于归集和存档。我们使用 3 个文件,分别记录任务(task.org,用于存储任务)、日志(journal.org,用于写日志)和便笺(memos.org,用于暂时存放还不能归类的东西)。
(defconstorg-agenda-dir(expand-file-name"agenda/"org-directory))定义task.org文件的路径,因为它多次被用到:
(defconstorg-agenda-file-tasks(expand-file-name"tasks.org"org-agenda-dir))因为任务条目可能需要在不同的类别间移动(比如:从 appointments 移动到 work),设置目标位置:
(org-refile-targets`((,org-agenda-file-tasks.(:maxlevel.1))(nil.(:maxlevel.1))))2 设置基础任务状态
我们定义两组任务状态,第一组未完成状态包括 TODO(待做)、NEXT(下一个)、DOING(在做),已完成状态包括 DONE(完成);另一组未完成状态包括 PENDING(待定),已完成状态包括 DELEGATED(指派)和 CANCELED(取消)。NEXT、DOING 可用于蕃茄工作法。
;; 定义TODO关键词:! 表示切换到该状态时会自动增加时间戳,;; @ 表示切换到该状态时要求输入文字说明,如果同时设定 @ 和 !,使用“@/!”;;; | 符号表示“完成”状态的分界线。(org-todo-keywords'((sequence"TODO(t)""NEXT(n!)""DOING(i!)""|""DONE(d@/!)")(sequence"PENDING(p@/!)""|""DELEGATED(g@/!)""CANCELED(c@/!)")))将任务标记为 DONE 时,自动记录时间并打开备注提示:
(org-log-donet)我们对不同的 TODO 关键字定义不同的外观:
(org-todo-keyword-faces;TODO关键词的外观'(("TODO".(:background"DarkOrange":foreground"black":weightbold))("PENDING".(:background"LightGreen":foreground"gray":weightbold))("DONE".(:background"azure":foreground"Darkgreen":weightbold))("CANCELED".(:background"gray":foreground"black"))))任务状态需要按C-c C-t循环切换任务状态,但这比较慢,所以定义可以使用C-c C-t KEY通过菜单直接切换到对应状态。
(org-use-fast-todo-selectiont);可使用 =C-c C-t KEY= 通过菜单直接切换到对应状态在操作状态转换时,将状态转换记录放入 LOGbook 抽屉,任务文件显得更清爽:
(org-log-into-drawert); 将状态转换记录放入 LOGbook 抽屉在切换任务状态时,标题可以添加标签,这可以通过设置org-todo-state-tags-triggers变量实现。("ACTIVE" . t)表示添加,("ACTIVE")表示删除。
(org-todo-state-tags-triggers;状态改变时自动增删tags`(("DOING"("ACTIVE".t))(done("ACTIVE"))))3 捕获 - 快速记录任务
“捕获”(capture)功能让你能随时随地、不打断当前工作流的情况下,快速记录一个任务或想法。使用捕获功能需要设置捕获模板。捕获的任务和日程分别放在task.org文件的“Tasks”和“Appointments”标题下,日志放在journal.org,暂存放在memos.org。
("t""Todo"entry(file+headline,org-agenda-file-tasks"Tasks")"*TODO%?\n Entered on %U\n %a")("a""Appointment"entry(file+headline,org-agenda-file-tasks"Appointments")"* %? :APPNT:\n Entered on %U\n %a")("j""Journal"entry(file+olp+datetree,(expand-file-name"journal.org"org-agenda-dir))"* %?\n Entered on %U")("m""Memo"entry(file,(expand-file-name"memos.org"org-agenda-dir))"* %?\n Entered on %U")4 事件优先级
给事件赋予优先级是时间管理的一种重要思想。根据事件的重要性和紧急性,可以用“四象限管理法”将事件划分为 4 类:重要且紧急(A)、重要但不紧急(B)、紧急但不重要©、不紧急也不重要(无标记)。处理它们的原则是:
- A 类必须减少它。如果你总有 A 类事情,说明时间管理有问题。
- 尽可能地把时间花在 B 类事情上,以减少 A 类事件。
- C 类授权给别人做
- D 类尽量少做
我们可以给任务清单添加优先级,并配置不同的颜色:
(org-highest-priority?A)(org-lowest-priority?C)(org-default-priority?C)(org-priority-faces'((?A.(:background"red":foreground"white":weightbold))(?B.(:background"DarkOrange":foreground"white":weightbold))(?C.(:background"yellow":foreground"DarkGreen":weightbold))))* [#A] 优先级最高 * [#B] 次高优先级 * [#C] 次次高优先级5 Timestamp(时间戳)
时间戳分为活动时间戳(active timestamp,用尖括号包裹)和不活动时间戳(Inactive timestamp,用方括号包裹)。
时间戳通常与 SCHEDULED(org-schedule, C-c C-s)和 DEADLINE(org-deadline, C-c C-d)结合,用于控制日程提醒方式,当然我们也可以只使用 timestamp(org-time-stamp, C-c .)在日历中显示事件而不提醒。SCHEDULED表示计划时间,DEADLINE表示截止时间,而单纯的时间戳通常用来表示一个约会(appointment)。还有一种 inactive timestamp(org-time-stamp-inactive, C-c !)可用于记录事件的发生时间,但不会显示在日历中(比如记录任务完成时间)。
* SCHEDULEDD 任务 SCHEDULED: <2025-10-05 日> * DEADLINE 任务 DEADLINE: <2025-10-05 日> * 日程安排 <2025-10-05 日>DEADLINE 会在截止时间前就提醒,SCHEDULED 则只会在计划时间点提醒。不管是 DEADLINE 还是 SCHEDULED,都会在过期而没有被标记为完成时(org-todo, C-c C-t),显示过期提醒,直到被标记为完成。对于设置为重复的事件,标记完成并不会让任务彻底结束,任务彻底完成不再重复需使用 org-agenda-todo(C-- 1 C-c C-t),以数字前缀参数“-1”运行 org-agenda-todo,结束重复事件。
在设置时间戳时,可以以天单位调整时间(S-left/S-right),也可以以周为单位(S-up/S-down)。还可以在设置时间戳时计算时间段的间隔(C-c C-y)。
5.1 基本形式
<2022-09-17 六>,[2022-09-17 六],<2022-09-17 六 14:00>,<2022-09-17 六 14:00-15:00>两个时间戳用‘–’连接起来就定义了一个时间段:<2022-09-17 六>--<2022-09-18 日>,连续使用 C-c . 可以创建时间段。
5.2 重复间隔
重复间隔有3种:
- +(表示每隔一个间隔重复一次,每个间隔的事件都必须完成,不能跳过不做);
- ++(表示每隔一个间隔重复一次,如果前面有多个没做,直接跳过);
- .+(表示从完成的时间重新计算间隔)。
间隔可以是 h(hour)、d(day)、w(week)、m(month)、y(year)。当然还需要在这几个字母前面加上一个数字,如:+2d, .+2w 等。
如果用 .+3d/5d 这样的形式,通常用于设置 habits,表示最少每5天,最多每3天执行一次。
5.3 修改默认提醒时间
在设置 Deadline 之后,默认会提前一周开始每天在 agenda 界面里显示,如果不需要提前这么久,可以重新设置提醒时间:
* 只提前一天提醒 DEADLINE: <2022-09-17 六 -1d>5.4 重复事件的表示
重复事件的表示有多种方法:
- 使用 +1w 这样的重复器,问题是没办法指定终止点,而且中间某个事件单独有变动的话没有办法更改;
- 使用 diary 方法,问题是方法复杂,且只有桌面 emacs 系统才能支持,移动设备不支持;
- 使用复制多个事件的方法,即使用 org-clone-subtree-with-time-shift(C-c C-x c)来快速复制,复制时可以指定复制次数和时间偏移,非常方便。好处是可以单独某个事件而不会影响其他的,不利的地方就是这多个事件之间没有关联性,不能统一修改。TODO: 如果在复制的时候添加一个 Property,指明这些事件实际是同一个事件,那就可以统一进行修改了。
使用 diary 可以表达比 orgmode 更复杂的日程安排,但不能使用 orgmode 强大的日程处理能力。如果要导入 ics 文件,可以在 scratch 中运行类似(icalendar-import-file "/home/duhaibo/archives/2025/2025-26-1课表.ics" "~/.emacs.d/diary")的代码,即可自动导入 ics 文件中的日程安排。
6 任务进度状态跟踪
6.4 标题子任务
org-mode 没有提供统计标题子任务完成进度的方法,如果确实需要,可以自己定义以下函数:
(defunmy/org-update-progress-percentage()"计算当前标题的完成进度"(interactive)(save-excursion(org-back-to-headingt)(let((level(org-outline-level))(total0)(done0));; 遍历所有子标题(org-map-entries(lambda()(when(and(=(org-outline-level)(1+ level))(org-entry-get(point)"ITEM"))(cl-incftotal)(when(string=(org-get-todo-state)"DONE")(cl-incfdone))))nil'tree)(org-set-property"PERCENTAGE"(format"[%d/%d]"done total)))))比如,有一个任务列表的执行状况如下:
* 项目任务 ** TODO 任务一 ** TODO 任务二 ** DONE 任务三 CLOSED: [2025-10-05 日 19:11] :LOGBOOK: - State "DONE" from [2025-10-05 日 19:11] :END:如果要统计这 3 项任务完成了几项,就可以对标题“项目任务”使用自定义的my/org-update-progress-percentage函数来统计,统计结果如下:
* 项目任务 :PROPERTIES: :PERCENTAGE: 1/3 :END: ** TODO 任务一 ** TODO 任务二 ** DONE 任务三 CLOSED: [2025-10-05 日 19:11] :LOGBOOK: - State "DONE" from [2025-10-05 日 19:11] :END:之所以把完成进度放在属性里,而不是在标题后面加上方括号显示进度,是因为在标题后面加方括号是有歧义的。标题下的列表的进度使用的是这个标记,如果子标题也使用这个标记,两个操作会相互冲突。
6.5 复选框子任务
对于以“[ ]”开头的列表, 会被当作复选框。这样就形成了局部的子任务,适用于将一个任务划分成几个简单的步骤,或者将任务分派给不同的小组或员工。
* 开发任务 [2/4] - [X] 需求分析 - [X] 技术设计 - [ ] 编码实现 - [ ] 测试验证我们不需要手动给列表添加复选框,只需要在列表项上按C-c C-x C-r(org-toggle-radio-button),即可给整个列表都加上复选框,还会把光标所在的列表项标记为完成。如果还要给任务列表添加新项目,可以按M-S-RET(org-insert-todo-heading)。
按C-c C-c(org-toggle-checkbox)会改变复选框的状态,步骤的状态变化会自动改变上级步骤/任务的完成进度。
如果各步骤是有顺序的,则可以按C-c C-x o(org-toggle-ordered-property),给标题添加ORDERED属性(或取消),这样列表就只能“逐步标记为完成”。
如果手动更改了某些内容导致列表的完成进度显示有误,可以按C-c #(org-update-statistics-cookies)刷新显示进度。