在org-mode中使用LOGBOOK中的时间戳进行自定义搜索

时间:2011-11-07 16:27:00

标签: search logging time org-mode

我想创建一个自定义日程搜索,它会根据LOGBOOK中的时间条目找到TODO项目。具体来说,我想根据标记进入等待状态的时间戳找到标记为WAITING的项目。这些条目如下所示:

:LOGBOOK:
- State "WAITING"     from "TODO"    [2011-11-02 Wed 15:10] \\
  Emailed so-and-so about such-and-such.
:END:

我可以使用日志中的信息吗?我使用的是7.5版,但必要时可以升级。

谢谢!

编辑:一个用例可能是找到等待状态超过一周的WAITING待办事项。 (这通常意味着我需要再次对某人进行攻击。)

2 个答案:

答案 0 :(得分:4)

以下应该做你需要的。您只需调整自定义议程命令即可适合您的用例。 (在测试和配置时,我使用了我的TODO关键字)。这段代码的一部分可能会复制内置组织函数的工作,特别是因为它类似于Scheduled和Deadline方法/过期行为,但我看不到任何可重用的特定函数。

自定义命令中使用的实际函数如下。

(defun zin/since-state (since todo-state &optional done all)
  "List Agenda items that are older than SINCE.

TODO-STATE is a regexp for matching to TODO states.  It is provided to
`zin/find-state' to match inactive timestamps.
SINCE is compared to the result of `zin/org-date-diff'.  If
`zin/org-date-diff' is greater than SINCE, the entry is shown in the
Agenda. 
Optional argument DONE allows for done and not-done headlines to be
evaluated.  If DONE is non-nil, match completed tasks.
Optional argument ALL is passed to `zin/find-state' to specify whether
to search for any possible match of STATE, or only in the most recent
log entry."
  (let ((next-headline (save-excursion (or (outline-next-heading) (point-max)))))
    ;; If DONE is non-nil, look for done keywords, if nil look for not-done
    (if (member (org-get-todo-state)
                (if done
                    org-done-keywords
                  org-not-done-keywords))
        (let* ((subtree-end (save-excursion (org-end-of-subtree t)))
               (subtree-valid (save-excursion
                               (forward-line 1)
                               (if (and (< (point) subtree-end)
                                        ;; Find the timestamp to test
                                        (zin/find-state todo-state subtree-end all))
                                   (let ((startpoint (point)))
                                     (forward-word 3)
                                     ;; Convert timestamp into days difference from today
                                     (zin/org-date-diff startpoint (point)))))))
          (if (or (not subtree-valid)
                  (<= subtree-valid since))
              next-headline
            nil))
      (or next-headline (point-max)))))

以下函数通过重新搜索转发查找日志条目。

(defun zin/find-state (state &optional end all)
  "Used to search through the logbook of subtrees.

Tests to see if the first line of the logbook is a change of todo
status to status STATE
- Status \"STATE\" from ...
The search brings the point to the start of YYYY-MM-DD in inactive timestamps.

Optional argument END defines the point at which to stop searching.
Optional argument ALL when non-nil specifies to look for any occurence
of STATE in the subtree, not just in the most recent entry."
  (let ((drawer (if all "" ":.*:\\W")))
    (re-search-forward (concat drawer ".*State \\\"" state "\\\"\\W+from.*\\[") end t)))

最后一个函数确定今天与上述函数找到的时间戳之间的天数差异。

(defun zin/org-date-diff (start end &optional compare)
  "Calculate difference between  selected timestamp to current date.

The difference between the dates is calculated in days.
START and END define the region within which the timestamp is found.
Optional argument COMPARE allows for comparison to a specific date rather than to current date."
  (let* ((start-date (if compare compare (calendar-current-date))))
    (- (calendar-absolute-from-gregorian start-date) (org-time-string-to-absolute (buffer-substring-no-properties start end)))
    ))

使用上述功能的两个示例自定义议程命令。第一个匹配您的用例,您只需将“PEND”更改为“WAITING”即可匹配正确的关键字。第二个查找超过30天前完成的DONE关键字(而不是查找与我/上个月匹配的月份的时间戳,就像我在第一个评论中链接的示例中所做的那样)。

(setq org-agenda-custom-commands
      (quote (("T" "Tasks that have been pending more than 7 days." tags "-REFILE/"
               ((org-agenda-overriding-header "Pending tasks")
                (org-agenda-skip-function '(zin/since-state 7 "PEND"))))
              ("A" "Tasks that were completed more than 30 days ago." tags "-REFILE/"
               ((org-agenda-overriding-header "Archivable tasks")
                (org-agenda-skip-function '(zin/since-state 30 "\\\(DONE\\\|CANC\\\)" t))))
              )))

答案 1 :(得分:2)

除了Jonathan Leech-Pepin的回答,如果您想查看CLOSED:配置添加的(setq org-log-done 'time)抽屉,您可以像这样改进zin/find-state功能:

(defun zin/find-state (state &optional end all)
  (let ((drawer (if all "" ":.*:\\W" "CLOSED:")))
    (or (re-search-forward (concat drawer ".*State \\\"" state "\\\"\\W+from.*\\[") end t)
        (re-search-forward (concat drawer ".*\\[") end t))))

PS:这只是对答案的改进,正确答案是Jonathan的答案。