我是一个刚接触 emacs 的新手,接触目的主要是为了实现任务管理。
现在的问题是:
我在进行任务管理的过程中,尽量让每个任务都有自己的 SCHEDULED
和 DEADLINE
,即使它们彼此互为父子任务。因此,许多父子任务都会带着不同的 SCHEDULED
和 DEADLINE
同时出现在 agenda 任务视图中。
有时,当我想完成其中一个任务时,我会发现它是一个父任务,然后我不得不找到它的最后一级子任务,然后再完成这些处于最后一级的子任务。父任务在任务视图中的出现并不能让我直接完成它,只会让我感到混乱。
所以,我想让任务视图只显示处于最后一级的子任务,它们是树枝的末端,是迷宫的外部,是积木的第一层,我想直接看到并处理它们。
我了解到 emacs 是非常自由的软件,在 Google 一番过后,我没有找到已有的解决方案,所以我在此寻求帮助。
期望各位大佬能随意丢出任何可能有用的信息,从一个链接到已有的解决方案,都提前在此表示感谢!
用 org-agenda-skip-function
应该可以,如果方便的话最好提供一个简单的 org 示例文本。
VagrantJoker:
org-agenda-skip-function
这是org 示例文本
* TODO task1
** TODO task1.1
*** TODO task1.1.1
*** TODO task1.1.2
** TODO task1.2
* TODO task2
** TODO task2.1
** TODO task2.2
理想效果是,只显示
TODO task1.1.1
TODO task1.1.2
TODO task1.2
TODO task2.1
TODO task2.2
这些都是最后一级的子任务
主要是现在相关知识不足,不知道在 org-mode 中该怎么识别哪些任务是最后一级的子任务,也就是如何过滤筛选。
大佬说的org-agenda-skip-function
我去了解一下,如果有更详细的信息,欢迎大佬发出来,感谢
你对于任务的划分有点问题,应当是所有子任务全部完成后,父任务应当自动被标记为完成状态。
没有必要为每个任务设置 schedule 和 deadline.
另外可以看看 GitHub - Trevoke/org-gtd.el: A package for using GTD with org-mode 这个包,我认为是较好实现了 David Allen 的 GTD 流程的包。
1 个赞
大佬你可以当作,我想得到一个只显示最后一级子任务的视图,就算是只给子任务设定 schedule 和 deadline ,有一个只显示最后一级子任务的视图也是很方便的,我可以看到最后一级子任务都有哪些,是否有哪些忘记设置schedule 和 deadline 了,这是一个自动化的过程。
谢谢大佬推荐的包,我会去尝试用用,不过 “只显示最后一级子任务的视图” 我还是想要的。
(defun my/skip-parent-todo-entries ()
"Skip TODOs that are not the last level."
(if (save-excursion (org-goto-first-child))
(or (outline-next-heading) (point-max))
(if (org-entry-is-todo-p)
nil
(org-end-of-subtree t))))
(setq org-agenda-custom-commands '(("t" "Show last level TODOs"
((todo ""
((org-agenda-skip-function #'my/skip-parent-todo-entries)))))))
你可以试试,应该没什么问题。
这里用了 org-agenda-custom-commands
相关用法可以看 Custom Agenda Views (The Org Manual)
1 个赞
感谢大佬!很好用,完美符合预期效果
给其他有需要的人:搭配 [%]
和 以下配置 体验更好
;; 强制TODO的状态切换依赖(父任务必须等子任务完成才能完成)
(setq org-enforce-todo-dependencies t)
;; 设置父任务自动完成,当子任务全部完成
(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)
再次感谢!
org-gtd 就可以只显示一个project 下的第一个子任务,标记完成后自动显示下一个子任务,直到所有子任务完成。整个项目从org-agenda 中就不显示了。
哈哈,这样感觉是我想法在另一个方向的完善版本,都是专注于最外层的子任务。
感谢大佬,我都会试试看的。
大佬我又遇到个小问题,还是与这个视图有关。
我想把org-goto-first-child
替换成org-goto-first-todo-child
,当然此处的org-goto-first-todo-child
很大可能是不存在的,我想自定义出来这个函数,想看看替换后是什么效果。或者说,我预想了一个效果,想自定义这个函数来实现。
这是示例文本
* TODO 测试1
** TODO 测试1.1
*** DONE 测试1.1.1
CLOSED: [2024-02-25 Sun 08:34]
*** DONE 测试1.1.2
CLOSED: [2024-02-25 Sun 08:34]
** TODO 测试1.2
*** TODO 测试1.2.1
*** DONE 测试1.2.2
CLOSED: [2024-02-25 Sun 08:46]
我想显示出TODO 测试1.1
,虽然这个任务已经没有ToDo子任务了,但它本身有时会是一个长期的ToDo父任务,会时不时往下面添加ToDo子任务,所以它不会被完成,并且我希望它在没有子任务时显示在任务视图中。
我预想了这个思路,不过对语法不太熟悉,短时间查不到直接相关的内容,所以希望大佬提点一下。
那你可以直接抄 org-goto-first-child
,中间修改下正则就好。
这是我现在满意的配置
;; 强制TODO的状态切换依赖(父任务必须等子任务完成才能完成)
(setq org-enforce-todo-dependencies t)
(defun my/org-goto-first-todo-child (&optional element)
"Goto the first child with a TODO status, even if it is invisible.
Return t when a child was found. Otherwise don't move point and
return nil."
(if (org-element--cache-active-p)
(let ((heading (org-element-lineage
(or element (org-element-at-point))
'(headline inlinetask org-data)
t)))
(when heading
(unless (or (eq 'inlinetask (org-element-type heading))
(not (org-element-property :contents-begin heading)))
(let ((pos (point)))
(goto-char (org-element-property :contents-begin heading))
(if (re-search-forward
(concat org-outline-regexp-bol "\\(TODO\\|SCH\\|DOING\\|WAIT\\)")
(org-element-property :end heading)
t)
(progn (goto-char (match-beginning 0)) t)
(goto-char pos) nil)))))
(let (level (pos (point)) (re (concat org-outline-regexp-bol "\\(TODO\\|SCH\\|DOING\\|WAIT\\)")))
(when (org-back-to-heading-or-point-min t)
(setq level (org-outline-level))
(forward-char 1)
(if (and (re-search-forward re nil t) (> (org-outline-level) level))
(progn (goto-char (match-beginning 0)) t)
(goto-char pos) nil)))))
(defun my/skip-parent-todo-entries ()
"Skip TODOs that are not the last level."
(if (save-excursion (my/org-goto-first-todo-child))
(or (outline-next-heading) (point-max))
(if (org-entry-is-todo-p)
nil
(org-end-of-subtree t))))
(setq org-agenda-custom-commands
'(("q" "Agenda for the next 31 days - Show last level TODOs"
((agenda ""
((org-agenda-start-day "-6d")
(org-agenda-span 37)
(org-agenda-show-all-dates nil)
(org-agenda-skip-function #'my/skip-parent-todo-entries)))))
("w" "Show last level TODOs and sort by scheduled-up"
((todo ""
((org-agenda-skip-function #'my/skip-parent-todo-entries)
(org-agenda-sorting-strategy '(scheduled-up))))))))
不再使用"自动完成父任务",因为喜欢手动标注DONE
,不喜欢任务不经过我同意就自己变成DONE
。使用过程中,发现"自动完成父任务"的配置需要每一个父子任务都加上[/]
或[%]
才能自动更新状态,这一点需要注意。
配置中的\\(TODO\\|SCH\\|DOING\\|WAIT\\)
是我个人的TODO
类任务状态,可根据自己的实际情况自行调整。
感谢 @VagrantJoker 大佬提点,让我能找到解决问题的正确思路。非常感谢!