【问题标题】:Is there a way to calculate org-mode heading properties based on sub heading todo-keywords?有没有办法根据子标题 todo-keywords 计算 org-mode 标题属性?
【发布时间】:2020-05-24 00:04:00
【问题描述】:

这就是我使用 org-capture 记录我的一天的方式

*** 2020-05-14 Thursday
:PROPERTIES:
:DoneA: 1
:DoneB: 1
:DoneC: 0
:Done: 0
:Kill: 1
:Gone: 1
:Rate: 5
:END:
:LOGBOOK:
CLOCK: [2020-05-14 Thu 04:55]--[2020-05-14 Thu 05:05] =>  0:10
:END:
**** DONE [#A] task a
**** GONE [#A] another task a
**** DONE [#B] task b
**** KILL other task

我手动计算并键入每个属性 并使用简单速率手动填充速率属性

对于 DONE [#A] 我给分数 5,#B 3,KILL 2,GONE -5 所以 Rate PROPERTY 是 = 5

是否有内置函数或emacs根据org-todo-keywords计算子标题并将其放在上级标题PROPERTIES中?

我的 elisp 技能不够好,无法制作自定义函数

【问题讨论】:

    标签: emacs org-mode


    【解决方案1】:

    没有这样的功能(这将取决于您要查找的内容的详细信息以及您希望如何记录它)但肯定有构建您自己的构建块,所以我鼓励您提高您的 elisp 技能,尽管我会尝试在下面给出一个激励性的例子来说明你将如何去做。

    首先要知道的是,Org 模式提供了a powerful functionorg-map-entries,它们可以遍历一组选定的标题,并在访问每个标题时应用任意函数。例如。这是一个简单的使用示例(直接来自手册 - 参见上面的链接),用于计算子树​​中匹配某个表达式 match 的条目数:

    (defun count-tasks (match)
      (length (org-map-entries t match 'tree)))
    

    如果您定义此函数,请将光标放在感兴趣日期的标题上(在您的示例中为*** 2020-05-14 Thursday),然后像这样调用它:

     ESC-ESC-: (count-tasks "/+DONE) RET
    

    它将返回子树中 DONE 条目的数量 - 在您的示例中,该数量应为 2。

    要知道的第二件事是有一个Property API,它提供了在标题上获取(org-entry-get)和设置(org-entry-put)属性的功能。例如,您可以通过这样做将“完成”属性设置为子树中@9​​87654331@ 任务的数量(我假设您的光标仍像以前一样位于标题处):

      ESC-ESC-: (org-entry-put (point) "Done" (format "%d" (count-tasks "/+DONE")) RET
    

    我们对任务进行计数,将数字转换为带有format 的字符串,并添加(或修改)名为Done 的属性以将字符串化的数字作为值。

    这些是碎片。你现在必须把它们放在一起做你想做的事。有些匹配有点复杂,例如要计算优先级为A 的所有DONE 标题,您需要说(count-tasks "PRIORITY=\"A\"/+DONE")

    因此,您只需为要计算的每个项目执行此操作,并设置适当的属性,同时记住每个计数,以便计算您的费率。这只是这些计数的加权和,如果您对向量有所了解,您可能会意识到它是两个向量的dot (scalar) product:权重向量和计数向量,您可以通过将相应元素相乘得到将两个向量加在一起并添加所有结果(顺便说一句,您的权重没有完全指定:您缺少 DoneC 类别的权重 - 我选择在下面为该类别添加权重 1)。在 lisp 中有很多方法可以做到这一点,具体取决于您如何表示这些向量。举个简单的例子,我可以将它们表示为元素列表,然后将速率实现为两个列表上的 map-reduce 操作:

    (defun rate (counts)
      (let ((weights '(5 3 1 2 -5)))
       (seq-reduce #'+ (mapcar* #'* weights counts) 0)))
    

    您应该阅读mapcar*seq-reduce 的文档字符串:它们非常有用(APL 是一种大量使用这些操作的语言),但如果您觉得有点晦涩难懂,您也可以使用循环实现它:

    (defun rate-iter (counts)
      (let ((weights '(5 3 1 2 -5))
            (rate 0))
        (while counts
          (setq rate (+ rate (* (car counts) (car weights)))
                counts (cdr counts)
                weights (cdr weights)))
        rate))
    

    然后您可以按照与上述完全相同的方式将其作为属性输入:

    ESC-ESC-: (org-entry-put (point) "Rate" (format "%d" (rate counts)))
    

    这些是碎片,但您仍然需要编写一些代码才能将它们组合在一起。 希望这会有所帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-11-15
      • 1970-01-01
      • 1970-01-01
      • 2017-07-08
      • 1970-01-01
      • 2020-09-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多