1. 从TODO到DONE:org todo到底解决了什么问题
1.1 折腾了三十四篇,我为什么还在坚持用todo
写到第三十四篇,说实话连我自己都没想到。这个系列最开始只是想记录几个键位,结果越写越长,从 org-mode 的基本编辑一路写到 noweb 代码块,中间还穿插了一堆易用性配置。今天这篇算是把最核心的一块补上——org todo。
如果你还没用过 org-mode 的 todo 功能,我建议你停下来想想自己平时是怎么管任务的。我见过很多人用备忘录、用微信文件传输助手、用桌面便签,结果任务一多就乱,做完的划掉,没做完的几乎就消失了。org todo 解决的正是这件事:让任务有一个从出生到消灭的完整生命周期,而且所有记录都留在本地纯文本里,不依赖任何云服务、不绑定任何平台。
标题里这个"折腾"两个字,其实体现了大多数 Emacs 用户的真实状态。你从网上抄一段配置,跑起来发现不够用,再调,再改,直到它变成你自己的东西。org todo 就是这样——它不是一个开箱即用的功能,而是给你一套状态机,你再根据自己的习惯定义 keyword、标签、优先级、截止时间,最终做出来的任务系统长什么样,完全由你自己决定。
1.2 理解 org todo 的两条主线
org todo 虽然在界面上看起来只是标题前多了几个大写单词,但它的设计背后有两条核心主线:状态流转和元数据记录。
状态流转好理解,一个任务从 TODO 开始,中间可能经历 IN PROGRESS、WAITING 之类的中间态,最后变成 DONE 或者 CANCELLED。org-mode 会按照你定义的顺序循环切换这些状态,C-c C-t 就是切换状态的快捷键。
元数据记录则更深入一些。org todo 可以给任务打上开始时间、完成时间、截止期限、计划日期、标签、优先级、笔记记录等,这些元数据最终会被 org-agenda 汇总,变成一张你每天、每周的任务视图。换句话说,todo 并不仅仅是一个标记功能,它其实是整个 org-mode 任务管理体系的入口。
理解了这两条主线,你再去看市面上各种 todo 插件,比如 org-super-agenda、org-edna、org-ql,就会发现它们都是在给这两种能力做增强,而不是另起炉灶。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 核心概念与关键词设计:从TODO到DONE的状态机
2.1 状态关键字:不只是TODO和DONE
很多人刚接触 org todo 时,以为就是 TODO 和 DONE 两个词来回切换。实际上,org-mode 的状态关键字完全由你定义,而且可以定义多组序列,每组序列互相独立。默认配置是:
elisp复制(setq org-todo-keywords
'((sequence "TODO(t)" "DONE(d)")))
这行配置的含义是:定义一组名为 sequence 的状态序列,包含 TODO 和 DONE 两个关键字,括号里的字母是快捷键。当你按下 C-c C-t t,当前标题就会从普通文本变成 TODO 状态;再按一次 C-c C-t d,就会变成 DONE。
但你肯定很快就会觉得不够用——任务不可能只有两种状态。我自己的配置是这样的:
elisp复制(setq org-todo-keywords
'((sequence "TODO(t)" "IN PROGRESS(s!)" "WAITING(w@)" "|" "DONE(d!)" "CANCELLED(c@)")))
这里有几个细节值得展开说。
垂直竖线 | 左边是"未完成"状态,右边是"已完成"状态。org-mode 会在这组状态之间循环,但有一条规则——当你在未完成状态按下 C-c C-t 继续往后切时,只会循环左侧的状态;已经进入右侧的完成状态后,再切换会回到左侧第一个状态。所以 | 其实是一个分界线,我一般把它理解为"活"和"死"的分界。
括号里的感叹号 ! 表示进入该状态时自动记录时间戳,在标题下方插入一行 - State "DONE" from "IN PROGRESS" [2025-01-18 Sat 16:32]。而 @ 表示进入该状态时弹出备注窗口,要求你输入说明。比如进入 WAITING 状态时,org-mode 会强制我写一句为什么在等待、等的是谁,这样两三天后回看时不会一脸茫然。
2.2 快捷键 C-c C-t 的逻辑与快速操作技巧
C-c C-t 是状态切换的核心快捷键,按一次进入下一个状态,如果你想直接跳到某个目标状态,最快的办法是 C-c C-t 然后按关键字括号里的字母。比如我的配置里,IN PROGRESS 是 s,WAITING 是 w,DONE 是 d,整个切换过程可以两秒内完成。
如果你嫌按三次键麻烦,还有两个更快的操作方式:
C-c C-x C-o在TODO序列中循环切换,但它只会在未完成的几个状态之间轮转,不会跳到DONE。- 在标题上直接右键,用鼠标选择状态,适合偶尔用鼠标的场景。
另外,org-mode 还支持将 todo 状态作为一个"关键字+标题"的复合结构插入。比如你在任意标题上执行 org-todo 后,标题会被改写成 TODO 标题文字;对 DONE 状态的标题执行 org-todo,它并不会像普通 C-c C-t 那样循环,而是直接把 TODO 单词拿掉,把标题恢复成纯文本。这个行为对很多人来说算是个坑,我一度以为是自己配置坏了,后来翻文档才发现这是设计如此。如果你希望 DONE 之后删掉状态,需要额外配置:
elisp复制(setq org-treat-insert-todo-heading-as-state-change t)
不过说实话,我不建议这么做。保持标题带关键字,你能在 org-agenda 里快速过滤,也方便用 org-ql 做复杂查询。
2.3 待办优先级:三段式A/B/C够用吗
org todo 的优先级就是字母加一个井号,格式是 [#A]、[#B]、[#C],默认只有这三个等级。设置优先级的方式有三种:
C-c ,弹出选择菜单,直接输入字母。S-up和S-down循环切换(从[#A]切到[#B]再切到[#C],循环往复)。- 直接在标题里手写
[#A]并保存。
优先级在 org-agenda 视图中会直接影响排序,A 排最前,C 排最后。如果你觉得三段不够用,可以自定义更多:
elisp复制(setq org-highest-priority ?A)
(setq org-lowest-priority ?E)
(setq org-default-priority ?B)
这段配置把优先级范围扩展到 A 到 E,默认值是 B。我个人的体会是,三段就足够了。任务管理的关键是判断"做不做",而不是把优先级细分成五档然后选择困难。真要说有什么值得调的,我觉得是 org-default-priority 的重要性——如果你不设置这个变量,默认优先级是 B,但很多人根本不知道这个默认值,导致 agenda 里大量任务都是 B 级,排序效果大打折扣。我把默认优先级设成 C,只有真正重要的任务才手动升到 A。
3. 时间维度:SCHEDULED、DEADLINE、时间戳与重复任务
3.1 SCHEDULED 和 DEADLINE 到底有什么区别
这是 org todo 里最常被问到的两个概念,也是最容易混淆的地方。我从自己的使用经验给你一个理解方式:
SCHEDULED 是你打算开始做这件事的日期。比如我计划周五下午写周报,就在标题下插入 SCHEDULED: <2025-01-17 Fri>。org-agenda 会把今天到期的 SCHEDULED 任务显示在当天的日程里。
DEADLINE 是任务的截止时间。比如论文这周五必须交,就插入 DEADLINE: <2025-01-17 Fri>。org-mode 会提前在议程视图里用"最近几天"的方式提醒你,默认提前 14 天就会开始显示倒计时。
插入方法也很简单:在标题下方任意位置,C-c C-s 插入 SCHEDULED 并调出日期选择器,C-c C-d 插入 DEADLINE,C-c . 插入普通时间戳。
这两个字段的区别,我用一个生活化类比给你讲清楚:SCHEDULED 像闹钟,它告诉你"到点该启动了";DEADLINE 像交卷铃声,它告诉你"再不做就来不及了"。两者不一定同时存在,但很多任务确实需要同时设置。比如"完成项目申报书"——SCHEDULED 设为下周一,DEADLINE 设为下周五,中间那几天就是你的缓冲窗口。
如果不想用日期选择器,也可以手写时间戳格式。org-mode 的时间戳支持两种表示:<2025-01-17 Fri> 表示"当天一整天",<2025-01-17 Fri 14:00> 表示"具体时刻"。后者在插入时可以用 C-u C-c .,会多一个时间输入步骤。
3.2 时间戳格式与日记范围(Active vs Inactive)
在 org todo 里,时间戳还分主动和被动两种。主动时间戳是尖括号 <2025-01-17 Fri>,会出现在 agenda 日历中;被动时间戳是方括号 [2025-01-17 Fri],只做记录,不参与调度。
比如我写一篇读书笔记,想记录"2025-01-17 读完了这本书",就不要用主动时间戳,否则它会被塞进 agenda 里当作日程显示。用方括号写就好:[2025-01-17 Fri]。插入被动时间戳的快捷键是 C-c C-[,或者 C-c !。
这个细节非常实用。很多人只学会了 C-c . 插入主动时间戳,结果日记、笔记里全是尖括号日期,agenda 里密密麻麻全是"某天读了文章""某天写了条想法"这类没有任何调度含义的记录。时间戳是很好的元数据,但要分场景——需要提醒和调度的用主动,纯记录的用被动。
3.3 重复任务:周期调度怎么写
重复任务是 org todo 里我用了很久才彻底搞懂的部分,因为它的语法太紧凑了。一个简单的例子:
org复制* TODO 每周写部门周报
SCHEDULED: <2025-01-13 Mon 09:30 +1w>
这个 +1w 表示任务完成后,下一次自动排到一周后。但如果你只设置 SCHEDULED: <2025-01-13 Mon 09:30 +1w>,org-mode 在你标记 DONE 时会自动把 SCHEDULED 改成 2025-01-20 Mon 09:30,非常顺手。
重复任务的语法还有三种前缀,很多人分不清,我专门整理过:
| 语法 | 含义 | 例子 |
|---|---|---|
+1w |
从完成日期算起,隔一周 | <2025-01-13 Mon +1w>,如果 1 月 15 日才写完,下次排到 1 月 22 日 |
++1w |
从任务原定日期算起,隔一周 | 无论何时完成,只要在周一的周期内,下次仍然排到下周一 |
.+1w |
从今天算起,隔一周 | 适合"做完后一周再提醒"的场景,比如定期复查 |
我的使用经验是:固定节奏的任务用 ++,比如每周一上午站会;灵活节奏的任务用 +,比如"每完成一次记录,一周后再写一次";而 .+ 用得最少,因为 + 已经覆盖了绝大多数需求。
另外,当一个重复任务被标记为 DONE 时,org-mode 会生成一个带"重复"标记的新任务,同时保留原任务作为历史记录。如果你想查看一个重复任务到底重复了多少次,用 org-occur 搜索标题里的固定文字即可。
4. 任务依赖:ORDERED 与 BLOCKER 的组合技巧
4.1 为什么单靠TODO和DONE不够用
状态机解决的是"单任务的生命周期",但真实工作里的任务往往有前后依赖。比如我写技术方案,得先做调研,再写文档,最后评审。如果简单地把三个任务都标成 TODO,你很难保证顺序——总是有人会先写完文档才发现调研还没做完。
org-mode 原生提供了两种机制来处理这种依赖关系:ORDERED 属性让同一标题下的子任务必须按顺序完成;BLOCKER 属性让某个任务在依赖任务未完成时无法被标记为 DONE。
4.2 ORDERED:子任务顺序锁
给标题设置属性 ORDERED: t 后,org-mode 会检查同级子任务的 todo 状态。假设结构是:
org复制* TODO 写技术方案
:PROPERTIES:
:ORDERED: t
:END:
** TODO 调研竞品
** TODO 编写文档
** TODO 内部评审
没有 ORDERED 属性时,你可以把"内部评审"先标成 DONE,然后"调研竞品"还挂着 TODO,看起来非常混乱。有了 ORDERED: t,org-mode 会强制要求你必须按顺序处理,后一个任务在任务所处级别上比前一个高,就无法被标记为 DONE。
具体行为是:它会在你尝试把未按顺序的任务标记为 DONE 时,弹出一个错误信息,告诉你 TODO state change from TODO to DONE was blocked。这个报错很明显,不用担心看不出原因。
不过要注意,ORDERED 只对同一父标题下的同级子任务生效,它不会去检查孙子任务。如果你的任务层级有三层,需要把 ORDERED 加到每一个需要顺序控制的父标题上。
4.3 BLOCKER:用表达式控制任务的"可完成性"
BLOCKER 属性比 ORDERED 更灵活,它支持多种表达式,最常用的格式是指定前驱任务的 ID 或标题。例如:
org复制* TODO 发布文章
:PROPERTIES:
:BLOCKER: 写文章 排版
:END:
* TODO 写文章
* TODO 排版
这里 BLOCKER: 写文章 排版 是指匹配标题包含"写文章"和"排版"的任务。两个任务都变成 DONE 后,"发布文章"才能被标记为 DONE。
BLOCKER 还支持 previous 关键字,表示依赖于同级任务中位于当前任务之前的、最近的那个任务。比如:
org复制* TODO 阶段一
* TODO 阶段二
:PROPERTIES:
:BLOCKER: previous
:END:
这样阶段二在阶段一完成前无法被标记为 DONE。
我实际用下来,ORDERED 更省心,因为不需要为每个任务写 BLOCKER 表达式;但 BLOCKER 更精细,可以做到跨层级、跨文件的依赖关系。跨文件依赖需要在两个任务的 PROPERTIES 中记录 ID:,然后 BLOCKER: 目标ID 才能生效。这个配置过于繁琐,我一般不用,除非任务管理到了非常正式的阶段。
4.4 用 org-edna 实现更现代的依赖关系
如果你觉得 ORDERED 和 BLOCKER 的用法太原始,想用更现代的方式管理任务依赖,社区推荐的是 org-edna。这个插件提供了一套类似条件宏的注入机制,我简单展示一下:
elisp复制(use-package org-edna
:ensure t
:config
(org-edna-mode 1))
配置完之后,可以在任务属性里写:
org复制* TODO 发布文章
:PROPERTIES:
:TRIGGER: 写文章(now()) 排版(now())
:BLOCKER: 写文章(chain()) 排版(chain())
:END:
这表示"发布文章"在完成时,会触发"写文章"和"排版"两个子任务立即变为当前状态;同时,它自身完成前会被"写文章"和"排版"的链式状态拦住。我个人的感受是:org-edna 的学习曲线高,但一旦你理解了 chain() 和 now() 的含义,它能处理很多复杂场景,比如"所有子任务完成时自动将父任务标记为 DONE"。
如果你还没到多任务联动的阶段,先用 ORDERED 就够了,别急着上 org-edna——折腾成本不低。
5. 标签、优先级和org-agenda:让todo真正可控
5.1 标签:给任务打上可检索的维度
todo 任务加标签,一是为了分类,二是为了在 org-agenda 中过滤。在标题末尾用冒号包裹文字就表示一个或多个标签:
org复制* TODO 撰写技术周报 :工作:写作:
这个任务同时具有"工作"和"写作"两个标签。插入标签的快捷方式是在标题上按 C-c C-x C-t(org-set-tags-command),会弹出输入框,支持从已有标签列表中选择,输入标签名后按 : 分隔,最后按回车完成。
标签本身只是字符串,想有层级则可以用冒号分隔前缀,比如 :工作:项目A: 和 :工作:项目B:,在 agenda 中按 工作 匹配时会命中所有子标签,按 项目A 匹配时只会命中更精确的那个。
5.2 标签过滤的实际用法
我每天看任务时不是直接打开文件,而是打开 org-agenda。按 C-c a m 进入标签匹配视图,输入 工作 就能看到所有带"工作"标签的 TODO 和 DONE 任务。
如果你想用标签组合做更复杂过滤,org-mode 的匹配语法支持 +标签(必须包含)、-标签(不能包含)、|(或)。比如:
org复制+工作+紧急 | +家庭+紧急
这个表达式能匹配"带工作标签且紧急"或"带家庭标签且紧急"的任务。虽然语法简单,但组合起来已经能覆盖绝大多数筛选需求。
5.3 org-agenda 自定义视图:把 todo 转化为日程
我个人最依赖的功能是 org-agenda。你说 todo 是任务,但如果只有任务没有时间维度,它还是孤立的。org-agenda 可以把不同文件中带 SCHEDULED 和 DEADLINE 的 todo 任务汇聚到一个界面里,让你按天、按周查看所有任务。
基础配置:
elisp复制(global-set-key (kbd "C-c a") #'org-agenda)
(setq org-agenda-files '("~/org/"))
把 ~/org/ 下的所有 org 文件都作为 agenda 文件,C-c a a 打开周视图。周视图默认显示本周的 SCHEDULED 和 DEADLINE 任务,按日期分组。
如果默认视图不满足需求,可以自定义命令。比如我配置了一个"只看工作流"的命令:
elisp复制(setq org-agenda-custom-commands
'(("w" "工作流任务"
((agenda "")
(alltodo)
(tags "+工作")))))
按下 C-c a w 后,会同时显示日程、所有未完成任务、带"工作"标签的任务。这样一个窗口就把"今天该干什么"和"所有待办里有哪些工作项"都列出来了。
5.4 优先级在 agenda 中的排序逻辑
org-agenda 视图会给任务排序:首先是按到期日期,然后是优先级。对于同一天到期的任务,优先级由高到低排列,[#A] 在最前。如果你觉得这个排序不符合自己的习惯,可以调整 org-agenda-sorting-strategy 变量,它是一个列表,决定排序策略的优先级顺序:
elisp复制(setq org-agenda-sorting-strategy
'((agenda habit-down time-up user-defined-up priority-down category-keep)
(todo priority-down category-keep)
(tags priority-down category-keep)))
我这套配置的意思是:在 agenda 视图中,习惯动作优先,然后按时间升序,再按用户定义排序,最后按优先级从高到低;在 todo 和 tags 视图中,直接按优先级从高到低排序。
6. 通过捕获(Capture)快速录入TODO:打破"忘了记"的魔咒
6.1 为什么任务管理系统总是用不起来
很多人的任务管理系统最后都会荒废,原因不是功能不够强大,而是"录入太麻烦"。打开 Emacs,找到目标文件,跳到正确位置,插入标题,设置优先级,设置提醒——这一套流程下来,在真正忙碌的工作节奏里,早就劝退了。
org-capture 就是为了解决这个问题设计的。它允许你通过一个快捷键,立即弹出一个输入框,输入完标题,按 C-c C-c 保存,任务就被放入你指定的文件中。整个过程不到十秒,而且完全不打断你当前的编辑状态。
6.2 配置一个TODO的capture模板
基础配置如下:
elisp复制(setq org-capture-templates
'(("t" "Todo" entry (file+headline "~/org/inbox.org" "Tasks")
"* TODO %?\n%U\n%a\n" :clock-in t :clock-resume t)))
这段配置的含义是:
t是模板快捷键,输入C-c c t即可触发。- 模板标题是
Todo。 - 内容插入到
~/org/inbox.org文件中的Tasks标题下。 - 模板文本包含
%?(光标停留位置)、%U(当前时间戳)、%a(当前所在条目或链接),这样你从任一文件里捕获任务时,能自动带上来源。 :clock-in t表示捕获后自动进入时钟计时,:clock-resume t表示捕获结束恢复之前的时钟计时。
我的习惯是用一个专门收件箱文件 capture,然后每周整理一次,把 inbox 里的任务移动到对应的项目文件里。使用 org-refile 实现移动,快捷键是 C-c C-w。
6.3 快速记录想法的三个小技巧
除了创建正式 todo,我的 capture 模板里还有一个灵感型模板,用来快速记录一个想法或一段笔记:
elisp复制("n" "Note" entry (file+headline "~/org/inbox.org" "Notes")
"* %? :note:\n%U\n" :empty-lines 1)
这个模板会生成带 note 标签的条目,方便日后用标签搜索筛选。
另一个技巧是在模板里加 %^g,它会在捕获过程中提示你输入标签。比如:
elisp复制("* TODO %?\n:PROPERTIES:\n:CREATED: %U\n:END:\n%a" :jump-to-captured t)
这样每次捕获都能顺手把标签和创建时间写进去。
最后一个技巧是把 todo 的状态切换也纳入 capture 流程。比如创建任务时默认就是 TODO,那你可以在模板里直接写死状态,不用每次再按 C-c C-t。
7. 实践中的常见问题与排查思路
7.1 状态切换没有反应?先检查一件事
如果你按 C-c C-t 后没有切到下一个状态,最常见的原因是当前光标所在位置不是 org-mode 的标题行。org todo 依赖于标题,它只对一级到多级标题生效,如果光标在正文段落里按 C-c C-t,org-mode 不会做任何事。
另一个可能原因是,文件虽然打开了,但 major-mode 不是 org-mode。检查方法:M-x org-mode 手动切换一下,如果切换后一切正常,可以考虑给 auto-mode-alist 添加规则,让 .org 文件默认用 org-mode:
elisp复制(add-to-list 'auto-mode-alist '("\\.org\\'" . org-mode))
7.2 WAITING 和 CANCELLED 标记了但日期没记录
如果你配置了 ! 和 @,但状态切换后没有时间戳或没有弹窗,大概率是你没在状态关键字里加感叹号和 at 符号。注意这两者是配置在 org-todo-keywords 里的,不是在任务属性里:
elisp复制"WAITING(w@)"
这个 @ 表示每次进入 WAITING 状态时弹出备注窗口。如果你写的是 "WAITING(w)",就只是纯切换,不弹窗不记录。
7.3 org-agenda 里看不到某一个TODO任务
org-agenda 默认只显示 org-agenda-files 里的文件,如果你的任务散落在其他文件里,agenda 是看不到的。同时,只有带 SCHEDULED 或 DEADLINE 的 todo 任务才会出现在 agenda 的日期视图里。如果你只是简单地把标题标记为 TODO,没有设置任何日期,它不会出现在日期视图,只会在 (todo) 视图里出现。
排查思路是:先确认文件在 agenda files 里,再确认任务带日期字段。如果你想所有 TODO 都默认出现在今天的 agenda 中,可以设置:
elisp复制(setq org-agenda-todo-ignore-scheduled nil
org-agenda-todo-ignore-deadlines nil)
7.4 重复任务完成之后没有自动生成下一次
这个问题的根源通常是对 + 和 ++ 的语义理解偏差。+1w 是在完成日期上加一周,++1w 是在原定日期上加一周。如果你用的是 + 并且标记 DONE 后没有看到下一次任务,可能是你没有等足够久——org-mode 不会立刻把未来日期显示出来,它会在任务到期时(或即将到期时)出现在 agenda 里。你可以检查原任务是否被改写了日期,标题是否还保留 TODO 状态:
C-u C-c C-t 可以强制重新计算周期性任务的日期。
另外一个常见情况是重复任务没有写 SCHEDULED 或 DEADLINE,只写了时间戳,此时 org-mode 不会把它识别为重复任务。重复任务必须写在 SCHEDULED 或 DEADLINE 字段中。
7.5 org-todo-keywords 修改后旧文件状态不匹配
有时候你调整了状态序列,比如把原先的 TODO | DONE 改成了 TODO | DONE CANCELLED,旧文件里已有的 DONE 状态仍然能正常显示,但如果你用 org-todo-regexp 或 org-ql 做搜索,可能匹配不到某些自定义状态名。原因比较简单:状态序列是动态读取配置的,但已保存的标题文字不会自动改写。你需要手动把旧状态替换成新状态,或者用 org-todo-yesterday 之类的函数统一升级旧数据。
8. 把 org todo 融入工作流:我的实际配置与心得
8.1 一份可以直接抄的配置
写到这里,我把目前能稳定工作的一整套配置贴出来,你可以根据自己的习惯修改。我没有用太多外部包,尽量保持依赖少、可复制性强:
elisp复制(use-package org
:ensure t
:hook ((org-mode . visual-line-mode)
(org-mode . auto-fill-mode))
:bind (("C-c c" . org-capture)
("C-c a" . org-agenda))
:config
;; todo keywords
(setq org-todo-keywords
'((sequence "TODO(t)" "IN PROGRESS(s!)" "WAITING(w@)" "|" "DONE(d!)" "CANCELLED(c@)")))
;; 设置默认优先级
(setq org-default-priority ?C)
;; agenda files
(setq org-agenda-files '("~/org/"))
;; capture templates
(setq org-capture-templates
'(("t" "Todo" entry (file+headline "~/org/inbox.org" "Tasks")
"* TODO %?\n%U\n%a\n" :clock-in t :clock-resume t)
("n" "Note" entry (file+headline "~/org/inbox.org" "Notes")
"* %? :note:\n%U\n" :empty-lines 1)))
;; refile 目标
(setq org-refile-targets '((org-agenda-files :maxlevel . 3)))
;; 让 archiving 和 refile 更顺手
(setq org-refile-use-outline-path t)
(setq org-outline-path-complete-in-steps nil))
这套配置只解决最核心的问题:任务状态、日程视图、快速录入。如果你还想加标签,那就在模板里补 %^g;如果还想加日志记录,就开启 org-log-done。
8.2 不要为了折腾而折腾:给新手的三条建议
第一,先建立最小习惯。我见过不少人第一天就配了一堆插件,结果一天下来主要时间都花在折腾配置上,真正想管理的事情一件没做。建议你先只用默认的 TODO | DONE,把每天的任务录进去,坚持一周再说。
第二,状态不要一刀切太多。很多教程会建议你定义五六个状态,我实际用下来,TODO、IN PROGRESS、WAITING、DONE 四个就够用了,CANCELLED 可以靠 org-log-done 记录原因。状态多了,切换本身就会变成负担。
第三,定期回看 Agenda。任务系统如果没有复盘,数据就只是堆在那里。我每周日晚上会花十分钟整理下周的计划,做法很简单:打开 org-agenda,把未完的任务重新预估一下时间,要么改 deadline,要么把它移到下周的 SCHEDULED 里。
8.3 从“记录任务”到“掌控任务”
工具的价值在于最终你养成的习惯,而不在于你装了多少插件。org todo 的整个设计思路是围绕"状态+时间+上下文"来组织的,你越用它越会发现:它记录的不仅是"要做的事",还包括了这个任务的来龙去脉——什么时候创建的、什么时候开始做的、什么时候做完的、为什么会等待、卡在谁那里。这些细节本身就是非常有价值的时间资产。
所以我的建议是,别急着追求一步到位的复杂方案。先用 todo + deadline + 核心三态,跑通你自己的流程。等跑通之后,你自然会发现"这个任务不该继续做了""这个东西需要周期性地做",那时候再去研究 ORDERED、BLOCKER、重复任务和 org-edna,就会非常顺理成章。
9. 踩过几个坑之后,我留下的小建议
9.1 时刻记得“设置过的状态才是好状态”
如果你经常发现自己标题上没有 TODO 字样,那说明你还没把它真正用起来。org todo 并不是为了给你的标题增加几个大写单词,而是为了让你每次打开文件时一眼看出"现在有哪些事情还欠着"。我个人的经验是,凡是需要进一步动作的事项,要么改成 TODO 状态,要么直接写清下一步动作,不要留下一个只有标题没有状态的条目。这样你整理 inbox 时就不必每个条目都点开看看。
9.2 保持文件数量可控
org todo 用起来后,任务文件会越来越多,agenda 的加载速度也会变慢。我建议每半年做一次归档,把已完成的项目整体移入 archive.org,这个操作在 org-archive-subtree 快捷键 C-c C-x C-s 下非常方便。归档之后,agenda files 里保留的只有活跃项目,整体响应速度会快很多。
9.3 多设备同步时的注意点
如果你像我一样在公司和家里用同一份 org 文件,同步工具可以用 Git 或者网盘。但要注意,org todo 的时间戳和状态切换在同步过程中不会冲突,因为每个条目是纯文本,合并几乎没有问题。唯一需要留意的是多个设备同时编辑同一文件可能产生合并冲突。我目前的做法是:公司电脑和家里电脑共享一个 Git 仓库,每次切换设备前先 pull 一次,编辑完立即 push。这套方式比网盘可靠得多。
最后分享一个小技巧:在 org-agenda 周视图中,v 键可以切换显示方式,v d 是日视图,v w 是周视图,v m 是月视图。我刚开始用的时候经常在周视图和日视图之间来回切换,后来发现用 v 按一次就能循环,不用每次都按两三个键。
org todo 这个东西,说简单也简单,两个快捷键就能用起来;说复杂也复杂,状态、日期、标签、优先级、依赖、捕获、归档,每一层都有深度。这篇文章能帮你把最核心的骨架搭起来,剩下的,就看你怎么在每天的记录中慢慢找到最适合自己的节奏了。
