问题 组织模式:在议程视图中过滤标签?


当议程构建其视图时,是否可以过滤标签?我尝试过以下内容仅显示与工作相关的约会:

("j" "Jobb"
   ((agenda ""
       ((org-agenda-skip-function '(org-agenda-skip-entry-if 'notregexp":jobb:"))))
    (tags-todo "jobb"))
    ((org-agenda-compact-blocks nil)))

仅当实际约会被直接标记时才有效,但如果约会从父标题继承其标记,则不会这样:

 * Tider                                                              :jobb:                                                                                                                                                         
 ** Millas arbetstider                                                                                                                                                                                                               
   <2012-04-11 ons 05:00-09:00>                                                                                                                                                                                                     
   <2012-04-12 tor 04:15-08:30>                                                                                                                                                                                                     
   <2012-04-13 fre 14:30-18:30>                           

有没有其他方法可以执行此操作,以便显示继承其标记的约会?


3040
2018-04-09 13:34


起源

Jobb是瑞典人的工作顺便说一句。 - Fredrik Jambrén


答案:


问题在于如何 org-agenda-skip-entries-if 与...互动 'notregexp。它将跳过任何不匹配的条目 :jobb:。即使后面的条目继承了标记,它也没有明确列出,因此它们被跳过。似乎没有任何内置方法匹配(或不匹配)使用的标签 org-agenda-skip-entries-if。如果有这样的功能,它可能是寻找标签的更有效的方法,但我不知道这样的功能。

您必须创建一个提供所需搜索格式的自定义函数。

如果您将议程命令更改为:

("j" "Jobb"
         ((agenda ""
                  ((org-agenda-skip-function '(zin/org-agenda-skip-tag "jobb" 't))))
          (tags-todo "jobb"))
         ((org-agenda-compact-blocks nil)))

并定义 zin/org-agenda-skip-tag 如:

(defun zin/org-agenda-skip-tag (tag &optional others)
  "Skip all entries that correspond to TAG.

If OTHERS is true, skip all entries that do not correspond to TAG."
  (let ((next-headline (save-excursion (or (outline-next-heading) (point-max))))
        (current-headline (or (and (org-at-heading-p)
                                   (point))
                              (save-excursion (org-back-to-heading)))))
    (if others
        (if (not (member tag (org-get-tags-at current-headline)))
            next-headline
          nil)
      (if (member tag (org-get-tags-at current-headline))
          next-headline
        nil))))

你会得到我理解的你想要的议程视图。如果我向后退,并且未来3天的条目不应出现,则只需将功能更改为 (zin/org-agenda-skip-tag "jobb") 要么 (zin/org-agenda-skip-tag "jobb" 'nil),在这种情况下,它们是等价的。

议程视图

在这种情况下 test-new 是我正在使用的组织文件的名称,可以忽略它。我也设置了两个标题 TODO 在测试函数时让它们可见,因为我将议程限制为只有一个文件。

Week-agenda (W15):
Monday      9 April 2012 W15
Tuesday    10 April 2012
Wednesday  11 April 2012
  test-new:    5:00- 9:00 TODO Millas arbetstider                        :jobb::
Thursday   12 April 2012
  test-new:    4:15- 8:30 TODO Millas arbetstider                        :jobb::
Friday     13 April 2012
  test-new:   14:30-18:30 TODO Millas arbetstider                        :jobb::
Saturday   14 April 2012
Sunday     15 April 2012

================================================================================
Headlines with TAGS match: jobb
  test-new:   TODO Tider                                                  :jobb:
  test-new:   TODO Millas arbetstider                                    :jobb::

12
2018-04-10 15:08



这不是我所追求的,这不会使议程的一部分忽略所有没有用“jobb”标记的约会 - Fredrik Jambrén
糟糕,我误解了你的问题(回头看很清楚,我只是没有正确阅读)。我将编辑以提供一个可以做你想要的答案(或者似乎基于你的例子)。 - Jonathan Leech-Pepin
我没有从org-back-to-heading,所以我不得不用当前标题代替(save-excursion(预测(org-back-to-heading)(点))) - Kirk Kelsey
嗯,只有当扫描从标题开始时,它才会这样做,如果你在任何其他线上它将成功。我将编辑代码以包含对该案例的检查(在此上下文中仅在标题中使用时间戳)。 - Jonathan Leech-Pepin
这似乎有效,但有没有办法将其与标准相结合 org-agenda-skip-subtree-if? - avv


在使用Jonathan的答案中的函数几个月来进行这种逐块过滤之后,我发现自己想要能够处理更复杂查询的东西(比如其他块类型使用的匹配字符串),我想我d将此贴在此处,以便将来偶然发现这个问题。

编辑:最初的实现 my/org-match-at-point-p 现在有点过时了。组织模式源现在是词法范围的,它改变了合同 org-make-tags-matcher。它曾经是那样的 todo 和 tags-list 变量需要围绕调用动态确定范围 org-make-tags-matcher,而现在它们似乎被传递给从调用返回的函数。 (是的!这好多了!)我已经调整了下面的代码以匹配新版本,但我不再使用Org模式了,所以它只是经过了轻微的测试。

(defun my/org-match-at-point-p (match)
  "Return non-nil if headline at point matches MATCH.
Here MATCH is a match string of the same format used by
`org-tags-view'."
  (funcall (cdr (org-make-tags-matcher match))
           (org-get-todo-state)
           (org-get-tags-at)
           (org-reduced-level (org-current-level))))

(defun my/org-agenda-skip-without-match (match)
  "Skip current headline unless it matches MATCH.

Return nil if headline containing point matches MATCH (which
should be a match string of the same format used by
`org-tags-view').  If headline does not match, return the
position of the next headline in current buffer.

Intended for use with `org-agenda-skip-function', where this will
skip exactly those headlines that do not match." 
  (save-excursion
    (unless (org-at-heading-p) (org-back-to-heading)) 
    (let ((next-headline (save-excursion
                           (or (outline-next-heading) (point-max)))))
      (if (my/org-match-at-point-p match) nil next-headline))))

如果您仍在使用较旧版本的组织模式,则这是原始代码。请注意,此版本假定其中的文件 my/org-match-at-point-p 定义是词法范围的;如果没有,你可以安全地更换 my/defun-dyn 用一个简单的宏 defun

(defmacro my/defun-dyn (&rest def)
  "As `defun', but always in dynamic scope.
A function defined in this way ignores the value of
`lexical-binding' and treats it as if it were nil.

\(fn NAME ARGLIST &optional DOCSTRING DECL &rest BODY)"
  (declare (debug defun)
           (indent defun)
           (doc-string 3))
  `(eval '(defun ,@def) nil))

(my/defun-dyn my/org-match-at-point-p (match &optional todo-only)
  "Return non-nil if headline at point matches MATCH.
Here MATCH is a match string of the same format used by
`org-tags-view'.

If the optional argument TODO-ONLY is non-nil, do not declare a
match unless headline at point is a todo item."
  (let ((todo      (org-get-todo-state))
        (tags-list (org-get-tags-at)))
    (eval (cdr (org-make-tags-matcher match)))))

3
2017-10-30 20:56



我正在努力了解你的功能 my/org-match-at-point,我很难理解哪里 todo-only 进来。看看 org-make-tags-matcher 文档,匹配器应该用三个参数调用,并查看 这个 实施 org-tags-matcher,它的召唤完成了 todo-only,而你的不是。我在这里想念的是什么? - tariqk
看起来我的代码真的过时了。组织模式源现在是词法范围的,并且为了制作 org-make-tags-matcher 与此相关的是,匹配者的合同必须已经改变。我会用解释更新答案。 - Aaron Harris
至于 todo-only,我的回忆是,曾经是另一个变量,可以动态地围绕调用来改变匹配器的行为(所以我在参数列表中的声明就足够了),但这似乎已被删除。我认为匹配字符串语法可能已被增强;手册提到了一个 ! 我不认识的运营商。 - Aaron Harris
噢!嗨!非常感谢。这给了我一些我稍后需要追求的指示。 - tariqk